#include "HashBase.h"
#include "C:\libs\dirent\include\dirent.h"
#include <opencv2\opencv.hpp>
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

using namespace cv;

using namespace std;

static unsigned long calculateHash(Mat src){
	Mat img;
	int k = 0;
	if (src.channels() == 3)
	{
		cvtColor(src, src, CV_BGR2GRAY);
		img = Mat_<double>(src);
	}
	else
	{
		img = Mat_<double>(src);
	}

	resize(img, img, Size(32, 32));
	Mat imgDct;
	dct(img, imgDct);

	double dIdex[64];
	double mean = 0.0;
	uchar *ptr = imgDct.data;
	for (int i = 0; i < 8; ++i)
	{
		for (int j = 0; j < 8; ++j)
		{
			dIdex[k] = ptr[i + j * imgDct.cols];
			mean += ptr[i + j * imgDct.cols];
			++k;
		}
	}
	mean = mean / 64;
	unsigned long long hash = 0;
	for (int i = 0; i < 64; ++i)
	{
		if (dIdex[i] >= mean)
		{
			hash |= (unsigned long long)1 << i; // set 1 to bit i in hash
		}
	}
	return hash;
}

int findCollisionHash(int threshold, const char* nameDir1, const char* nameDir2)
{

	cout << ">< findCollisionHash " << threshold << " ><" << endl;

	ofstream out("C://work//photo//resultCollision.txt");

	if (!out.is_open())
	{
		cout << "out file not opend " << endl;
		return -1;
	}
	HashBase hashBase(threshold);
	int count = 0;
	int numProcessed = 0;

	DIR *dir1, *dir2;
	struct dirent *ent;
	if (((dir1 = opendir(nameDir1)) != NULL) && ((dir2 = opendir(nameDir2)) != NULL)){
		/*  all the files and directories within directory */
		while ((ent = readdir(dir1)) != NULL){
			cv::Mat img = cv::imread(String(nameDir1) + "\\" + ent->d_name);
			if (!img.empty()){
				//cout << "<" << ent->d_name << ">" << endl;
				unsigned long myHash = 0;
				myHash = calculateHash(img);
				hashBase.isInBase(ent->d_name, myHash, 0, out);
				++count;
				if (count % 50 == 0){
				//	cout << count << endl;
				}
				if (count > 100000){
					break;
				}
				numProcessed++;
			}
		}
		closedir(dir1);
	}
	else
	{
		cout << " ERROR input files not found !" << endl;
		return EXIT_FAILURE;
	}

	cout << "num valid photos in fst folder :" << count  << endl;
	out << " processed commerce images : " << count << endl;
	out << " numHashGroups : " << hashBase.numHashGroups() << endl;
	out << "start serching collisions " << endl;
	out << " collisions : " << endl;
	count = 0;

	unsigned long numCollisions = 0;

	/*  all the files and directories within directory */
	while ((ent = readdir(dir2)) != NULL)	{
		cv::Mat img = cv::imread(String(nameDir2) + "\\" + ent->d_name);
		if (!img.empty()){
			//cout << "<" << String(nameDir2) + "\\" + ent->d_name << ">" << endl;
			unsigned long myHash = 0;
			myHash = calculateHash(img);
			numCollisions += hashBase.isInBase(ent->d_name, myHash, 1, out);
			++count;
			if (count % 50 == 0){
			//	cout << count << endl;
			}
			if (count % 100000 == 0){
				cout << count << endl;
				break;
			}
			numProcessed++;
		}
	}
	closedir(dir2);

	cout << "_________________numCollisions : " << numCollisions << endl
		<< " num valid photos in sec folder : " << count << endl;

}

int  hammingDist(unsigned long x, unsigned long y){
	int dist = 0;
	for (int i = 0; i < 64; ++i){
		if (CHECK_BIT(x, i) != CHECK_BIT(y, i)){
			++dist;
		}
	}
	return dist;
}

int main(){
	//unsigned long x = 0, y = 53523453535;
	//cout << hammingDist(x, y);

	for (int i = 0; i < 25; ++i){
		findCollisionHash(i, "C:\\work\\photo\\detHash", "C:\\work\\photo\\random-photo");
	}
	return 0;
}