#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#include "obtc.h"
#include "singular.h"
#include<time.h>


//uint8_t const_data[200];

static const int hex2bin_tbl[256] = {
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};

bool hex2bin(unsigned char *p, const char *hexstr, size_t len)
{
	int nibble1, nibble2;
	unsigned char idx;
	bool ret = false;

	while (*hexstr && len) {
		if ((!hexstr[1])) {
			printf("hex2bin str truncated");
			return ret;
		}

		idx = *hexstr++;
		nibble1 = hex2bin_tbl[idx];
		idx = *hexstr++;
		nibble2 = hex2bin_tbl[idx];

		if (((nibble1 < 0) || (nibble2 < 0))) {
			printf("hex2bin scan failed");
			return ret;
		}

		*p++ = (((unsigned char)nibble1) << 4) | ((unsigned char)nibble2);
		--len;
	}

	if ((len == 0 && *hexstr == 0))
		ret = true;
	return ret;
}


int main(int argc, char **argv)
{
	uint8_t genesis_block[80];
	uint8_t hash[32];

	uint8_t last_prehash[32];
	uint8_t last_prehash2[32];
	uint8_t prehash_tab[32];
	uint8_t nonce_tab[8];
	char *prehash_str = "d76ffb1d8e31ec04579b0452b52bde7dbd088e912ab1b11ba924ff309ab44a43";//argv[1]; 
	char *nonce_str = "80aa59a7901f2502";//argv[2]; 
	//char *last_prehash_str = argv[3]; 
	//char *last_prehash_str2 = argv[4]; 

	hex2bin(prehash_tab, prehash_str, strlen(prehash_str)/2);
	hex2bin(nonce_tab, nonce_str, strlen(nonce_str)/2);
	//hex2bin(last_prehash, last_prehash_str, strlen(last_prehash_str)/2);
	//hex2bin(last_prehash2, last_prehash_str2, strlen(last_prehash_str2)/2);
	/*for (uint8_t i = 0; i<32;i++){
		printf("0x%x, ",prehash_tab[i]);
	}
	printf("\n");
	
	for (uint8_t i = 0; i<8;i++){
		printf("0x%x, ",nonce_tab[i]);
	}
	printf("\n");*/
	
	//uint8_t prehash[32] = {0x81,0x55,0x3a,0x69,0x5a,0x05,0x88,0x99,0x8c,0x41,0x37,0x92,0xe7,0x4c,0xe8,0xb8,0xf8,0xa0,0x96,0xd6,0x4b,0x3e,0xe4,0x73,0x87,0x37,0x24,0x34,0x48,0x5c,0x0b,0x6f};
	//uint8_t utime[8] = 	  {0x00,0x00,0x01,0x84,0x8c,0xa8,0x7c,0x49};
	uint8_t pad[32] =     {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
	//uint8_t nonce[8] =    {0x2f,0x84,0x00,0x00,0x0e,0xba,0x16,0x7c};

#if 0	
	//uint8_t prehash[32] = {0xa4,0x8f,0xae,0x69,0xeb,0x28,0xc7,0xe0,0x14,0x11,0x4f,0x01,0xae,0x60,0xc8,0xc3,0x82,0x73,0xc4,0x60,0x66,0xcf,0x95,0xd6,0x77,0x1a,0x55,0xd6,0x16,0xd7,0xa1,0x9a};//大端
	//uint8_t utime[8] =	  {0x00,0x00,0x01,0x87,0x22,0x1e,0xad,0x44};
	//uint8_t nonce[8] =	  {0x8e,0xd4,0x00,0x10,0x6b,0xe7,0xe4,0x00};
	//uint8_t nonce[8] =	  {0x8e,0xd4,0x00,0x12,0x27,0xc6,0x90,0xa0};
	//uint8_t nonce[8] =	  {0x8e,0xd4,0x00,0x32,0x0b,0x6b,0xd6,0xd1};


	//3f 9a aa c6 32 af 1a 4e 0e 1f ea 8a f8 e3 d5 32 b7 5a a4 71 b2 e4 ef fe a5 bd cc fa 3b dd b6 61
	uint8_t prehash[32] = {0x3f,0x9a,0xaa,0xc6,0x32,0xaf,0x1a,0x4e,0x0e,0x1f,0xea,0x8a,0xf8,0xe3,0xd5,0x32,0xb7,0x5a,0xa4,0x71,0xb2,0xe4,0xef,0xfe,0xa5,0xbd,0xcc,0xfa,0x3b,0xdd,0xb6,0x61};//大端
	uint8_t utime[8] =	  {0x00,0x00,0x01,0x87,0x21,0xeb,0x73,0x79};
	uint8_t nonce[8] =	  {0xa3,0xdd,0x02,0x10,0x1a,0x87,0xb4,0x70};




#else


	/*443e01000000ffff00000000
	e0af2a3ba173157d3f70c94aad742fdf16d9930fdfc9d6301e869bcef04ced6c
	e0af2a3ba173157d3f70c94aad742fdf16d9930fdfc9d6301e869bcef04ced6c
	dbee84288701000000000000901f25020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
	
	[2023-03-28 22:00:46.549] 00 cc 01 11 70 83 85 16 90 1f 25 02	 
	
	kas_pow_hash: in:e0af2a3ba173157d3f70c94aad742fdf16d9930fdfc9d6301e869bcef04ced6cdbee842887010000000000000000000000000000000000000000000000000000000000000000000070838516901f2502
	kas_pow_hash: out:dae78f5008d3b66f
	01a740ce33c812ba
	772b3f5763da7bc6
	da24cb6c00000000*/

	uint8_t prehash[32] = {0xe0,0xaf,0x2a,0x3b,0xa1,0x73,0x15,0x7d,0x3f,0x70,0xc9,0x4a,0xad,0x74,0x2f,0xdf,0x16,0xd9,0x93,0x0f,0xdf,0xc9,0xd6,0x30,0x1e,0x86,0x9b,0xce,0xf0,0x4c,0xed,0x6c};
	//uint8_t utime[8] = 	  {0x00,0x00,0x01,0x87,0x28,0x84,0xee,0xdb};
	uint8_t nonce[8] =    {0x02,0x25,0x1f,0x90,0x16,0x85,0x83,0x70};

#endif

	/*for (int i = 0; i < 32; ++i) genesis_block[i] = prehash[i];
	for (int i = 0; i < 8; ++i) genesis_block[i+32] = utime[7-i];
	for (int i = 0; i < 32; ++i) genesis_block[i+40] = pad[31-i];
	for (int i = 0; i < 8; ++i) genesis_block[i+72] = nonce[7-i];*/
	//uint8_t utime[8] = 	  {0x00,0x00,0x01,0x87,0x21,0xeb,0x73,0x79};
	//dbee8428870100000
	uint8_t utime[8] =	  {0x00,0x00,0x01,0x87,0x28,0x84,0xee,0xdb};

	for (int i = 0; i < 32; ++i) genesis_block[i] = prehash_tab[i];
	for (int i = 0; i < 8; ++i) genesis_block[i+32] = utime[7-i];
	for (int i = 0; i < 32; ++i) genesis_block[i+40] = pad[31-i];
	for (int i = 0; i < 8; ++i) genesis_block[i+72] = nonce_tab[i];

	clock_t start, finish; 
   	double Total_time; 
	uint32_t cnt = 0;;
	//while(1)
	{
		start = clock(); 
		opticalbtc_hash((const char*)&genesis_block, (char*)&hash, sizeof(genesis_block));
		finish = clock(); 
		Total_time = (double)(finish-start) / CLOCKS_PER_SEC; 
		printf( "\n cnt = %d, opticalbtc_hash run times %f seconds\n", cnt++, Total_time);

		for (int i=31; i>-1; i--) {
			printf("%02hhx", hash[i]);
		}
		printf("\n");
	}


	//if (hash[31] != 0 || hash[30] != 0){
	//	for (int i = 0; i < 32; ++i) genesis_block[i] = last_prehash[i];
	//	opticalbtc_hash((const char*)&genesis_block, (char*)&hash, sizeof(genesis_block));
	//}

	//if (hash[31] != 0 || hash[30] != 0){
	//	for (int i = 0; i < 32; ++i) genesis_block[i] = last_prehash2[i];
	//	opticalbtc_hash((const char*)&genesis_block, (char*)&hash, sizeof(genesis_block));
	//}

	if (hash[31] != 0 && hash[30] != 0){
		printf("reject\n");
	}

	return 0;
}


//g++ -std=c++11 *.cpp