/**
 * @file    shred.h
 * @brief   shred drive
 * @author  hendrik schutter
 * @date    03.05.2020
 */

#ifndef SHRED_H_
#define SHRED_H_

#include "../reHDD.h"

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include <libgen.h>


#include "tfdef.h"
#include "tfcore.h"
//#include "tfe.h"

#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif

#ifndef _TFNG_STREAM_CIPHER_DEFS
#define _TFNG_STREAM_CIPHER_DEFS
#endif

#define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6)						\
	do {										\
		KE_MIX(Y, X, k1 + k2, k3, TFS_KS01);					\
		KE_MIX(T, Z, k4 + x, k5 + k6, TFS_KS02);				\
											\
		BE_MIX(X, T, TFS_BS01); BE_MIX(Z, Y, TFS_BS02);				\
		BE_MIX(X, Y, TFS_BS03); BE_MIX(Z, T, TFS_BS04);				\
		BE_MIX(X, T, TFS_BS05); BE_MIX(Z, Y, TFS_BS06);				\
	} while (0)

#define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6)						\
	do {										\
		KE_MIX(Y, X, k1 + k2, k3, TFS_KS03);					\
		KE_MIX(T, Z, k4 + x, k5 + k6, TFS_KS04);				\
											\
		BE_MIX(X, T, TFS_BS07); BE_MIX(Z, Y, TFS_BS08);				\
		BE_MIX(X, Y, TFS_BS09); BE_MIX(Z, T, TFS_BS10);				\
		BE_MIX(X, T, TFS_BS11); BE_MIX(Z, Y, TFS_BS12);				\
	} while (0)


#define NOSIZE ((size_t)-1)

#define XRET(x) if (!xret && xret < x) xret = x

class Shred
{
protected:

public:

    Shred();
    ~Shred();
    void shredDrive(Drive* drive, int* ipSignalFd);

private:

    unsigned long blockcount = 0UL;
    long blockcount_max;
    double d32Percent;

    inline double calcProgress();
    inline void tfnge_init_iv(struct tfnge_stream *tfe, const void *key, const void *iv);
    inline void tfnge_init(struct tfnge_stream *tfe, const void *key);
    inline void tfng_encrypt_rawblk(TFNG_UNIT_TYPE *O, const TFNG_UNIT_TYPE *I, const TFNG_UNIT_TYPE *K);
    inline void tfnge_emit(void *dst, size_t szdst, struct tfnge_stream *tfe);

};

#endif  // SHRED_H_