#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
//put additional include files here

//put your own support static functions here
static bool _open_file(file& ff, const string& strFile, uint* pnSizeLow, uint* pnSizeHigh)
{
	WIN32_FILE_ATTRIBUTE_DATA fileInfo;
	if(!GetFileAttributesEx(strFile, 0, &fileInfo))
		return false;
	if(pnSizeLow)
		*pnSizeLow = fileInfo.nFileSizeLow;
	if(pnSizeHigh)
		*pnSizeHigh = fileInfo.nFileSizeHigh;

	//open the binary file
	if( !ff.Open(strFile, file::modeRead | file::typeBinary) )
		return false;
	
	return true;
}




void cmpfile(const string& fn1, const string& fn2, int& diff, int& byteoffset)
{
	file f1, f2;
	uint ns1a, ns1b, ns2a, ns2b;
	if(!_open_file(f1, fn1, &ns1a, &ns1b))
		///Cheney 2007-6-18 UPDATE_XF_ERR_THROW
		//XF_THROW("failed to open 1st file!")
		XF_THROW(XFERR_CMPFILE_FAILED_OPEN_1ST_FILE);
		///end UPDATE_XF_ERR_THROW
	
	if(!_open_file(f2, fn2, &ns2a, &ns2b))
	{
		f1.Close();
		///Cheney 2007-6-18 UPDATE_XF_ERR_THROW
		//XF_THROW("failed to open 2nd file!")
		XF_THROW(XFERR_CMPFILE_FAILED_OPEN_2ND_FILE);
		///end UPDATE_XF_ERR_THROW
	}
	///Cheney 2007-6-18 UPDATE_XF_ERR_THROW
	//printf("comparing\nfile1: %s\nfile2: %s\n", fn1, fn2);
	string strMsg;
	ocu_load_msg_str(XF_CMPFILE_COMPARING, &strMsg, fn1, NULL, fn2);
	warning_msg_box(strMsg, false, 'R');
	///end UPDATE_XF_ERR_THROW
	
	if(ns1a != ns2a || ns1b != ns2b)
	{
		///Cheney 2007-6-18 UPDATE_XF_ERR_THROW
		//printf("The two files are different in size:\nfile1: %d %d\nfile2: %d %d\n",ns1b, ns1a, ns2b, ns2a);
		ocu_load_msg_str(XF_CMPFILE_TWO_FILE_DIFF_IN_SIZE, &strMsg);
		string strfile;
		ocu_load_msg_str(XF_CMPFILE_FILE, &strfile);
		strMsg.Format("%s:\r\n%s1: %d %d\r\n%s2: %d %d", strMsg, strfile, ns1b, ns1a, strfile, ns2b, ns2a);
		warning_msg_box(strMsg, false, 'R');
		///end UPDATE_XF_ERR_THROW
		//goto end; ///--- Sim 07-05-2006 v8.0436 QA70-8732 FILE_COMPARE_1ST_DIFFERENCE
	}
	///--- Sim 07-05-2006 v8.0436 QA70-8732 FILE_COMPARE_1ST_DIFFERENCE
	/// open files just for get size only. so it should be close now.
	f1.Close();
	f2.Close();
	/// end FILE_COMPARE_1ST_DIFFERENCE
	
	///--- Sim 07-05-2006 v8.0436 QA70-8732 FILE_COMPARE_1ST_DIFFERENCE
	/*
	if(ns1b > 0)
	{
		out_str("files are too big, cannot compare");
		goto end;
	}
	vector<byte> vb1, vb2;
	vb1.SetSize(ns1a);
	vb2.SetSize(ns2a);
	if(f1.Read(vb1, vb1.GetSize()) != vb1.GetSize())
	{
		out_str("failed to read file 1");
		goto end;
	}
	if(f2.Read(vb2, vb2.GetSize()) != vb2.GetSize())
	{
		out_str("failed to read file 2");
		goto end;
	}
	// all read correctly, we can start the actual comparison
	bool bSame = true;
	uint nDiffAt = 0;
	for(uint ii = 0; ii < vb1.GetSize(); ii++)
	{
		if(vb1[ii] != vb2[ii])
		{
			bSame = false;
			nDiffAt = ii;
			break;
		}
	}
	if(bSame)
		out_str("The two files are identical.");
	else
		printf("Two files are different starting at byte offset %d\n", nDiffAt+1);
	
	diff = bSame? 0:1;
	byteoffset = nDiffAt;
	end:
	f1.Close();
	f2.Close();
	*/
	
	diff = file_compare((LPCSTR)fn1, (LPCSTR)fn2, &byteoffset);
	switch (diff)
	{
	case -1:
		///Cheney 2007-6-18 UPDATE_XF_ERR_THROW
		//out_str("Fail to open file.\n");
		ocu_load_msg_str(XF_CMPFILE_FAIL_OPEN, &strMsg);
		///end UPDATE_XF_ERR_THROW
		break;
	case 0:
		///Cheney 2007-6-18 UPDATE_XF_ERR_THROW
		//out_str("The two files are identical.");
		ocu_load_msg_str(XF_CMPFILE_TWO_FILE_IDENTICAL, &strMsg);
		///end UPDATE_XF_ERR_THROW
		break;
	case 1:
		///Cheney 2007-6-18 UPDATE_XF_ERR_THROW
		//printf("Two files are different starting at byte offset %d\n", byteoffset+1);
		int nByteOffset = byteoffset + 1;
		ocu_load_msg_str(XF_CMPFILE_TWO_FILE_DIFF_AT_START_BYTE_OFFSET, &strMsg, NULL, &nByteOffset);
		///end UPDATE_XF_ERR_THROW
		break;
	case 2:
		///Cheney 2007-6-18 UPDATE_XF_ERR_THROW
		//printf("Two files are different and offset overlow UINT.\n");
		ocu_load_msg_str(XF_CMPFILE_TWO_FILE_DIFF_AND_OFFSET_OVERLOW, &strMsg);
		///end UPDATE_XF_ERR_THROW
		break;
	}
	/// end FILE_COMPARE_1ST_DIFFERENCE
	
	warning_msg_box(strMsg, false, 'R');///Cheney 2007-6-18 UPDATE_XF_ERR_THROW
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int cmpfile_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return cmpfile_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	string strF1 = trGetN.fn1.strVal;
	string strF2 = trGetN.fn2.strVal;
	if(strF1.IsEmpty() || strF2.IsEmpty())
		bOKEnable = false;
	
	return false;
	

}

int cmpfile_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return false;
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void cmpfile_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{

}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int cmpfile_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
