/*
 * This code is released under the Microsoft Public License (MS-PL). See License.txt, below.
 */
#include "stdafx.h"
#include "compare.h"
#include "create.h"
#include "get.h"

int CompareUnsignedLong(
	const void* a, 
	const void* b
	)
{
	return (int)(*(LPDWORD)a - *(LPDWORD)b);
}

int CompareFile(
	_TCHAR* path,
	_TCHAR* pszSrcPathWithoutFileName,
	DWORD idx,
	_TCHAR* ext,
	LPDWORD isOk,
	FILE* logFp
	)
{
	int cmpRetVh = _tcscmp(ext, _T(".vh"));
	int cmpRetSshd = _tcscmp(ext, _T(".sshd"));
	for (DWORD i = 0; i < idx; i++) {
		if (isOk[i] == FALSE) {
			continue;
		}
		_TCHAR szFilenameWithoutPath1[_MAX_PATH] = { 0 };
		_TCHAR szOutPath1[_MAX_PATH] = { 0 };
		FILE* FpSrc = CreateOrOpenFile(path, NULL, szOutPath1,
			szFilenameWithoutPath1, ext, _T("rb"), i, idx);
		if (!FpSrc) {
			continue;
		}
		DWORD SizeSrc = getFilesize(FpSrc);
		LPBYTE bufSrc = (LPBYTE)calloc(SizeSrc, sizeof(BYTE));
		if (!bufSrc) {
			OutputLastErrorNumAndString(_T(__FUNCTION__), __LINE__);
			FcloseAndNull(FpSrc);
			continue;
		}

		_TCHAR szFilenameWithoutPathVb1[_MAX_PATH] = { 0 };
		_TCHAR szOutPathVb1[_MAX_PATH] = { 0 };
		FILE* FpSrcVb = NULL;
		DWORD SizeSrcVb = 0;
		LPBYTE bufSrcVb = NULL;
		if (!cmpRetVh || !cmpRetSshd) {
			FpSrcVb = CreateOrOpenFile(path, NULL, szOutPathVb1,
				szFilenameWithoutPathVb1, _T(".vb"), _T("rb"), i, idx);
			if (!FpSrcVb) {
				FcloseAndNull(FpSrc);
				FreeAndNull(bufSrc);
				continue;
			}
			SizeSrcVb = getFilesize(FpSrcVb);
			bufSrcVb = (LPBYTE)calloc(SizeSrcVb, sizeof(BYTE));
			if (!bufSrcVb) {
				OutputLastErrorNumAndString(_T(__FUNCTION__), __LINE__);
				FcloseAndNull(FpSrc);
				FreeAndNull(bufSrc);
				FcloseAndNull(FpSrcVb);
				continue;
			}
		}

		for (DWORD k = i + 1; k < idx; k++) {
			if (isOk[k] == FALSE) {
				continue;
			}
			_TCHAR szFilenameWithoutPath2[_MAX_PATH] = { 0 };
			_TCHAR szOutPath2[_MAX_PATH] = { 0 };
			FILE* FpDst = CreateOrOpenFile(path, NULL, szOutPath2,
				szFilenameWithoutPath2, ext, _T("rb"), k, idx);
			if (!FpDst) {
				continue;
			}
			DWORD SizeDst = getFilesize(FpDst);
			BOOL bSame = FALSE;

			_TCHAR szFilenameWithoutPathVb2[_MAX_PATH] = { 0 };
			_TCHAR szOutPathVb2[_MAX_PATH] = { 0 };
			if (SizeSrc == SizeDst) {
				FILE* FpDstVb = NULL;
				DWORD SizeDstVb = 0;
				LPBYTE bufDstVb = NULL;
				if (!cmpRetVh || !cmpRetSshd) {
					FpDstVb = CreateOrOpenFile(path, NULL, szOutPathVb2,
						szFilenameWithoutPathVb2, _T(".vb"), _T("rb"), k, idx);
					if (!FpDstVb) {
						FcloseAndNull(FpDst);
						continue;
					}
					SizeDstVb = getFilesize(FpDstVb);
					bufDstVb = (LPBYTE)calloc(SizeDstVb, sizeof(BYTE));
					if (!bufDstVb) {
						OutputLastErrorNumAndString(_T(__FUNCTION__), __LINE__);
						FcloseAndNull(FpDst);
						FcloseAndNull(FpDstVb);
						continue;
					}
					if (SizeSrcVb == SizeDstVb) {
						fread(bufSrcVb, sizeof(CHAR), SizeSrcVb, FpSrcVb);
						fread(bufDstVb, sizeof(CHAR), SizeDstVb, FpDstVb);
					}
					else {
						FcloseAndNull(FpDst);
						FreeAndNull(bufDstVb);
						FcloseAndNull(FpDstVb);
						continue;
					}
				}
				LPBYTE bufDst = (LPBYTE)calloc(SizeDst, sizeof(BYTE));
				if (!bufDst) {
					OutputLastErrorNumAndString(_T(__FUNCTION__), __LINE__);
					FcloseAndNull(FpDst);
					if (!cmpRetVh || !cmpRetSshd) {
						FreeAndNull(bufDstVb);
						FcloseAndNull(FpDstVb);
					}
					continue;
				}
				fread(bufSrc, sizeof(CHAR), SizeSrc, FpSrc);
				fread(bufDst, sizeof(CHAR), SizeDst, FpDst);
				if (memcmp(bufSrc, bufDst, SizeDst) == 0) {
					if (!cmpRetVh || !cmpRetSshd) {
						if (memcmp(bufSrcVb, bufDstVb, SizeDstVb) == 0) {
							_ftprintf(logFp, _T("%s,%s,%s,%s\n"), 
								szFilenameWithoutPath1, szFilenameWithoutPath2, 
								szFilenameWithoutPathVb1, szFilenameWithoutPathVb2);
						}
						else {
							FreeAndNull(bufDst);
							FcloseAndNull(FpDst);
							FreeAndNull(bufDstVb);
							FcloseAndNull(FpDstVb);
							continue;
						}
					}
					else {
						_ftprintf(logFp, _T("%s,%s\n"), 
							szFilenameWithoutPath1, szFilenameWithoutPath2);
					}
					bSame = TRUE;
				}

				FreeAndNull(bufDst);
				if (!cmpRetVh || !cmpRetSshd) {
					FreeAndNull(bufDstVb);
					FcloseAndNull(FpDstVb);
				}
			}
			FcloseAndNull(FpDst);
			if (bSame) {
				_TCHAR szDups[_MAX_PATH] = { 0 };
				_tcsncpy(szDups, pszSrcPathWithoutFileName, _tcslen(pszSrcPathWithoutFileName));
				if (!PathAppend(szDups, szFilenameWithoutPath2)) {
					OutputLastErrorNumAndString(_T(__FUNCTION__), __LINE__);
					continue;
				}
				else {
					if (!MoveFileEx(szOutPath2, szDups, MOVEFILE_REPLACE_EXISTING)) {
						OutputLastErrorNumAndString(_T(__FUNCTION__), __LINE__);
						continue;
					}
				}
				if (!cmpRetVh || !cmpRetSshd) {
					_TCHAR szDups2[_MAX_PATH] = { 0 };
					_tcsncpy(szDups2, pszSrcPathWithoutFileName, _tcslen(pszSrcPathWithoutFileName));
					if (!PathAppend(szDups2, szFilenameWithoutPathVb2)) {
						OutputLastErrorNumAndString(_T(__FUNCTION__), __LINE__);
						continue;
					}
					else {
						if (!MoveFileEx(szOutPathVb2, szDups2, MOVEFILE_REPLACE_EXISTING)) {
							OutputLastErrorNumAndString(_T(__FUNCTION__), __LINE__);
							continue;
						}
					}
				}
			}
			OutputString(_T("\rCompare %s %4u and %4u"), ext, i + 1, k + 1);
		}
		FreeAndNull(bufSrc);
		FcloseAndNull(FpSrc);
		if (!cmpRetVh || !cmpRetSshd) {
			FreeAndNull(bufSrcVb);
			FcloseAndNull(FpSrcVb);
		}
	}
	if (idx > 1) {
		OutputString(_T("\n"));
	}
	return 0;
}
