#include "stdafx.h"

extern INT64 size;
extern Tick starttick;

int diffBitcasa(BitcasaAPI& API, param::paramdata& param)
{
	auto local = localsearch(param);
	auto remote = remotesearch(API, param);
	std::unordered_map<std::wstring, std::pair<fileentry, BitcasaFileItem>> difflist;

	for (auto it = local.begin(); it != local.end(); ++it){
		difflist[it->display].first = *it;
	}
	for (auto it = remote.begin(); it != remote.end(); ++it){
		difflist[it->display].second = *it;
	}

	int left = 0, right = 0;
	int samefile = 0, difffile = 0;
	std::vector<std::wstring> ret;
	size_t loop = 1, loopmax = difflist.size();;
	for (auto it = difflist.begin(); it != difflist.end(); ++it,loop++){
		std::wstring prefix = L"";
		bool lefton = !it->second.first.display.empty();
		bool righton = !it->second.second.display.empty();

		if (lefton && righton){
			left++;
			right++;
			if (param.ignoresize && param.ignoretime){
				prefix = L"(++)";
			}
			else {
				bool same = true;
				if (param.verbose){
					std::wcout << "\n" << it->first << "\n";
				}
				if (!param.ignoresize && !it->second.first.directory){
					// if the entry is directory, ignore the size.
					// (cannot get remote bitcasa directory size)
					auto sizeL = it->second.first.filesize;
					auto sizeR = it->second.second.size;
					same = same && (sizeL == sizeR);
					if (param.verbose){
						std::wcout << "left  size: " << sizeL << "\n";
						std::wcout << "right size: " << sizeR << "\n";
					}
				}
				if (!param.ignoretime){
					auto timeL = it->second.first.LastWriteTime;
					auto timeR = it->second.second.LastWriteTime;
					// ignore sub second
					FILETIME timeL2;
					SYSTEMTIME t1;
					FileTimeToSystemTime(&timeL, &t1);
					t1.wMilliseconds = 0;
					SystemTimeToFileTime(&t1, &timeL2);

					same = same && (CompareFileTime(&timeL2, &timeR) == 0);
					if (param.verbose){
						std::wcout << "left  time: " << UTF8toWideChar(filetimestr(timeL2)) << "\n";
						std::wcout << "right time: " << UTF8toWideChar(filetimestr(timeR)) << "\n";
					}
				}
				if (same && param.hashtype){
					std::wcerr << loop << "/" << loopmax << std::endl;
					if (!it->second.first.directory){
						std::wcerr << " local hash check:" << it->second.first.name << std::endl;
						it->second.first.hashstr = FileHash(it->second.first.absolutepath, it->second.first.filesize, param.hashtype);
					}
					if (!it->second.second.id.empty()){
						std::wcerr << " remote hash check:" << it->second.second.name << std::endl;
						it->second.second.hashstr = RemoteFileHash(API, it->second.second.id, it->second.second.size, param.hashtype);
					}
					same = same && (it->second.first.hashstr == it->second.second.hashstr);
					if (param.verbose){
						std::wcout << "left  hash" << it->second.first.hashstr;
						std::wcout << "right hash" << it->second.second.hashstr;
					}
				}
				prefix = (same) ? L"(==)" : L"(<>)";
				(same) ? samefile++ : difffile++;
			}
		}
		else if (lefton) {
			left++;
			prefix = L"(L )";
		}
		else if (righton) {
			right++;
			prefix = L"( R)";
		}
		else {
			// directory entry
			continue;
		}
		ret.push_back(prefix + it->first);
	}
	std::wcout << "left  only:" << ret.size() - right << std::endl;
	std::wcout << "right only:" << ret.size() - left << std::endl;
	std::wcout << "all:" << ret.size() << std::endl;
	if (samefile > 0)
		std::wcout << "same:" << samefile << std::endl;
	if (difffile > 0)
		std::wcout << "diff:" << difffile << std::endl;

	std::sort(ret.begin(), ret.end());
	std::copy(ret.begin(), ret.end(), std::ostream_iterator<std::wstring, wchar_t>(std::wcout, L"\n"));

	if (ret.size() != right)
		return 10;
	if (ret.size() != left)
		return 11;
	if (difffile > 0)
		return 12;
	return 0;
}
// 10 : left only exists
// 11 : right only exists
// 12 : time or size or hash difference exists
