#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
#include <GetNBox.h>
#include <Operation.h>
#include <ReportTree.h>
#include <report_utils.h>
#include <event_utils.h>
#include <..\Originlab\nlsf_utils.h>		///------ Folger 05/20/09 QA80-13638 FIT_COMPARE_DIALOG_FAILS_TO_OPEN_TO_DISPLAY_CORRECT_RESULT
#include <..\Originlab\wksOperation.h>



/*------------------------------------------------------------------------------*
 * Modification Log:															*
 * Iris 01/16/2007 IMPLEMENT_SSR_DF_ON_COMBINED_DATA							*
 * Echo 07/11/30 QA70-10589-P3 v8.0757	FITCMP_SUPPORT_POLY_ORDER				*
 * Echo 08/1/22 QA70-10975 v8.0790 FITCMP_RUNTIME_ERROR							*
 *	Folger 05/20/09 QA80-13638 FIT_COMPARE_DIALOG_FAILS_TO_OPEN_TO_DISPLAY_CORRECT_RESULT
 *	Folger 07/01/09 QA80-13774-P1 COMPARE_MODELS_FOR_FITTING_WITH_WEIGHT_FAILS_WHEN_NOT_OUTPUT_FIT_STATISTICS_TABLE
 *  Iris 12/25/2009 QA81-14890-S1 ADD_PREFERED_MODEL_TABLE						*
 *  Iris 12/25/2009 QA81-14890-S2 REPLACE_MODEL1_MODEL2_TO_REAL_FUNCTION_NAME	*
 *  Iris 12/25/2009 QA81-14890-S3 SET_TABLE_DEFAULT_CLOSE						*
 *	Echo 2/2/10 v8.1.89.54 qa-14890 CORRECT_TYPO								*
 *	Folger 10/09/2010 ORG-1228-P1 FIT_COMPARE_MODEL_EMPTY_FUNCTION_NAME_FOR_LINEAR_AND_POLYNOMIAL
 *	Folger 10/18/2010 ORG-1178 USE_MODEL_ONE_TWO_INSTEAD_OF_FUNCTION_NAME_FOR_TESTING_IN_FIT_COMAPRE_MODELS
 *------------------------------------------------------------------------------*/
static bool _get_all_xy_data(TreeNode& trGUI, vector& vX, vector& vY)
{
	TreeNode 	trInput = trGUI.InputData;
	
	DataRange 	dr;
	dr.Create();
	dr.SetTree(trInput);
	
	DWORD 	dwRules = DRR_GET_DEPENDENT | DRR_NO_FACTORS;
	int		nNumData = dr.GetNumData(dwRules);
	if(nNumData <= 0)
		return false;
	
	vX.SetSize(0);
	vY.SetSize(0);
	
	for( int ii = 0; ii < nNumData; ii++)
	{
		DWORD 	dwPlotID;
		vector 	vTempX, vTempY;
		dr.GetData( dwRules, ii, &dwPlotID, NULL, &vTempY, &vTempX);
		vX.Append(vTempX);
		vY.Append(vTempY);
	}
	return true;
}

static bool _get_create_combined_data_range(TreeNode& trGUI1, const TreeNode& trGUI2, Worksheet& wks, XYRange& drCombinedData)
{
	vector 	vX1, vY1, vX2, vY2;
	if( !_get_all_xy_data(trGUI1, vX1, vY1) || !_get_all_xy_data(trGUI2, vX2, vY2) )
		return false;
	
	vector 	vX, vY;
	vX.Append(vX1);
	vX.Append(vX2);
	vY.Append(vY1);
	vY.Append(vY2);
	if(vX.GetSize() != vY.GetSize())
		return false;
	
	/*
	uint	nSize = vY.GetSize();
	if( OE_NOERROR != ocmath_xy_remove_duplicates(&nSize, vX, vY) )
		return false;
	*/
	
	wks.SetSize(-1, 2);
	drCombinedData.Add(wks, 0, "X");
	drCombinedData.Add(wks, 1, "Y");
	drCombinedData.SetData(&vY, &vX);
	return true;	
}

static bool _calculate_on_combined_data(LPCSTR lpcszClass, const XYRange& dr, TreeNode& trStatsResult, LPCSTR lpcszModel = NULL, LPCSTR lpcszCateg = NULL)
{
	bool 	bOK;
	int 	nOption = 0;
	Operation& op = (Operation &)op_create(lpcszClass, bOK, nOption); 
	if(op == NULL)
	   return false;
	
	Tree 	trOp;
	op.GetTree(trOp);
	
	if ( !op.OnInitDataFromOCLT(trOp, trOp.GUI.InputData, dr, lpcszModel, lpcszCateg) )
	   return false;
	
	int            nAutoUpdate = 0;
	op.SetTree(trOp);
	op.OnNoEdit(nOption, nAutoUpdate, NULL);
	
	op.Calculate();
	
	op.GetTree(trOp);
	if (trOp.Calculation.RegStats)
		trStatsResult.Replace(trOp.Calculation.RegStats.FirstNode.Clone());
	
	op_destroy_on_cancel(op);
	return true;

}
///end IMPLEMENT_SSR_DF_ON_COMBINED_DATA

//static void _get_ftest(vector& vFtest, const double dSSR1, const double dSSR2, const double DF1, const double DF2)
//{
	//vFtest.SetSize(4);
	//vFtest[0] = ((dSSR1 - dSSR2)/dSSR2)/((DF1-DF2)/DF2);
	//vFtest[1] = fabs(DF1-DF2);
	//vFtest[2] = min(DF1, DF2);
	//vFtest[3] = 1 - fcdf(vFtest[0], vFtest[1], vFtest[2]);	
//}

static void _get_aic(vector& vAIC, const double dSSR, const double DF, const double dN)
{
	vAIC.SetSize(5);
	vAIC[0] = dSSR;
	vAIC[1] = dN;
	vAIC[2] = dN - DF;//number of parameters
	vAIC[3] = ocmath_AIC(vAIC[1], vAIC[2], vAIC[0], NULL);
}

static void _fitcmp_update_result_sheet(TreeNode& trRes, TreeNode trGUI)
{
	if (!fitcmp_check_stats(trRes))
	{
		XYRange 	dr;
		dr.Create();
		dr.SetTree(trGUI.InputData);
		string		strClass;
		trRes.GetAttribute(STR_ANALYSIS_ATTRIB, strClass);
		string		strModel;
		if(trRes.Notes.Model)
			strModel = trRes.Notes.Model.strVal;
		///Echo 08/1/22 QA70-10975 v8.0790 FITCMP_RUNTIME_ERROR
		int nOrder = (trGUI.Order) ? trGUI.Order.nVal : 2;
		///------- Folger 07/01/09 QA80-13774-P1 COMPARE_MODELS_FOR_FITTING_WITH_WEIGHT_FAILS_WHEN_NOT_OUTPUT_FIT_STATISTICS_TABLE
		//op_fit_on_data(strClass, dr, trRes, strModel, NULL, nOrder);
		op_fit_on_data(strClass, dr, trRes, strModel, NULL, nOrder, trGUI.InputData);
		///------- End COMPARE_MODELS_FOR_FITTING_WITH_WEIGHT_FAILS_WHEN_NOT_OUTPUT_FIT_STATISTICS_TABLE
		/*
		///Echo 07/11/30 QA70-10589 P3 v8.0757	FITCMP_SUPPORT_POLY_ORDER
		//op_fit_on_data(strClass, dr, trRes, strModel);
		op_fit_on_data(strClass, dr, trRes, strModel, NULL, trGUI.Order.nVal);
		///end FITCMP_SUPPORT_POLY_ORDER				
		*/
		///end FITCMP_RUNTIME_ERROR
	}
	
}

static void _fitcmp_model_update_report_tree(ReportTree& rtRootTable,
										TreeNode& trRes1, TreeNode& trRes2, 
										TreeNode& trGUI1, TreeNode&trGUI2,
										string strReport1, string strReport2, //string strFunction, 
										bool bFtest, bool bAIC,
										bool bFitParams, bool bFitStats, vector<string>& vstrFitReport)
{
	//////////////////////////////////////////////////////////////////
	// 	To get essential stats value
	//////////////////////////////////////////////////////////////////
	_fitcmp_update_result_sheet(trRes1, trGUI1);
	_fitcmp_update_result_sheet(trRes2, trGUI2);
		
	///------ Folger 10/09/2010 ORG-1228-P1 FIT_COMPARE_MODEL_EMPTY_FUNCTION_NAME_FOR_LINEAR_AND_POLYNOMIAL
	///// Iris 12/25/2009 QA81-14890-S2 REPLACE_MODEL1_MODEL2_TO_REAL_FUNCTION_NAME
	//string strModel1 = fitcmp_get_model(trRes1);
	//string strModel2 = fitcmp_get_model(trRes2);
	/////End REPLACE_MODEL1_MODEL2_TO_REAL_FUNCTION_NAME
	///------ Folger 10/18/2010 ORG-1178 USE_MODEL_ONE_TWO_INSTEAD_OF_FUNCTION_NAME_FOR_TESTING_IN_FIT_COMAPRE_MODELS
	//string strModel1 = fitcmp_get_model(trRes1, trGUI1);
	//string strModel2 = fitcmp_get_model(trRes2, trGUI2);
	string strModel1 = _L("Model1");
	string strModel2 = _L("Model2");
	///------ End USE_MODEL_ONE_TWO_INSTEAD_OF_FUNCTION_NAME_FOR_TESTING_IN_FIT_COMAPRE_MODELS
	///------ End FIT_COMPARE_MODEL_EMPTY_FUNCTION_NAME_FOR_LINEAR_AND_POLYNOMIAL
	
	double dSSR1, dSSR2, DF1, DF2, dN1, dN2;
	fitcmp_get_stats_value(trRes1, trRes2, &dSSR1, &dSSR2, &DF1, &DF2, &dN1, &dN2);
	//////////////////////////////////////////////////////////////////
	// 	Notes
	//////////////////////////////////////////////////////////////////
	
	report_tree_create(rtRootTable, _L("Fit Comparison of Models"));
	
	///Iris 12/25/2009 QA81-14890-S3 SET_TABLE_DEFAULT_CLOSE
	if( rtRootTable.Notes )
		set_table_open(rtRootTable.Notes, false);
	///End SET_TABLE_DEFAULT_CLOSE

	//////////////////////////////////////////////////////////////////
	// Description
	//////////////////////////////////////////////////////////////////
	fitcmp_add_descrp(rtRootTable, trRes1, trRes2, trGUI1, trGUI2, false, vstrFitReport);

	/// RVD 10/30/2007 v8.0737 qa7-10609 REPORT_FOOTNOTE_STYLE_THEME
	Tree trTheme;
	trTheme.Root.NameStyles.NameStyle1.Name.strVal = "ogFootNote";
	trTheme.Root.NameStyles.NameStyle1.Style.Color.nVal = 3;
	trTheme.Root.NameStyles.NameStyle1.Style.Font.Size.nVal = 16;
	trTheme.Root.NameStyles.NameStyle1.Style.Font.Bold.nVal = 1;
	/// end REPORT_FOOTNOTE_STYLE_THEME
	
	//////////////////////////////////////////////////////////////////
	// Prefered Model
	//////////////////////////////////////////////////////////////////
	/// Iris 12/25/2009 QA81-14890-S1 ADD_PREFERED_MODEL_TABLE
	ReportTable 	rtModel;
	int nPreferedModelTableID = FITCMP_PREFERED_MODEL;
	vector<string> 	vsModelTagName, vsModelLabels;
	vsModelTagName.Add("ModelName");
	vsModelLabels.Add(_L("Model Name"));
	string strCmpConclusion;
	if( bAIC || bFtest )
	{
		///Echo 2/2/10 v8.1.89.54 qa-14890 CORRECT_TYPO
		//rtModel = rtRootTable.CreateTable("PreferedModel", _L("Prefered Model"), nPreferedModelTableID++);
		rtModel = rtRootTable.CreateTable("PreferedModel", _L("Preferred Model"), nPreferedModelTableID++);
		///END CORRECT_TYPO
	}
	///End ADD_PREFERED_MODEL_TABLE
	
	//////////////////////////////////////////////////////////////////
	// Akaike's Information Criterion Test (AIC) 
	//////////////////////////////////////////////////////////////////
	if(bAIC)	
	{
		int ID = FITCMP_AIC;
		ReportTable rtAIC = rtRootTable.CreateTable("AIC", _L("Akaike's Information Criterion Test (AIC)"), ID);
		set_table_open(rtAIC);///Iris 12/25/2009 QA81-14890-S3 SET_TABLE_DEFAULT_CLOSE
		
		vector<string> vAICLabels(5), vAICTagName(5);
		vAICLabels[0] = vAICTagName[0] = _L("RSS");
		vAICLabels[1] = vAICTagName[1] = _L("N");
		vAICLabels[2] = vAICTagName[2] = _L("Params");	
		vAICLabels[3] = vAICTagName[3] = _L("AIC");
		vAICLabels[4] = _L("Akaike Weight");
		vAICTagName[4] = _L("Weight");	
			
		vector vAIC1, vAIC2;
		_get_aic(vAIC1, dSSR1, DF1, dN1);
		_get_aic(vAIC2, dSSR2, DF2, dN2);
		double dMinAIC = min(vAIC1[3],vAIC2[3]);
		double dDelta1 = vAIC1[3] - dMinAIC;
		double dDelta2 = vAIC2[3] - dMinAIC;
		vAIC1[4] = exp(-0.5*dDelta1)/(exp(-0.5*dDelta1)+exp(-0.5*dDelta2));
		vAIC2[4] = exp(-0.5*dDelta2)/(exp(-0.5*dDelta1)+exp(-0.5*dDelta2));
		
		/*
		double dDelta = vAIC1[3] - vAIC2[3];
		vAIC1[4] = exp(-0.5*dDelta)/(1+exp(-0.5*dDelta));
		vAIC2[4] = exp(0.5*dDelta)/(1+exp(0.5*dDelta));
		*/
		
		/// Iris 12/25/2009 QA81-14890-S2 REPLACE_MODEL1_MODEL2_TO_REAL_FUNCTION_NAME
		/*
		rtAIC.AddRow(_L("Model1"), vAIC1, _L("Model1"), vAICLabels, vAICTagName, ID++); 
		rtAIC.AddRow(_L("Model2"), vAIC2, _L("Model2"), vAICLabels, vAICTagName, ID++); 
		*/
		rtAIC.AddRow(_L("Model1"), vAIC1, strModel1, vAICLabels, vAICTagName, ID++); 
		rtAIC.AddRow(_L("Model2"), vAIC2, strModel2, vAICLabels, vAICTagName, ID++); 
		///End REPLACE_MODEL1_MODEL2_TO_REAL_FUNCTION_NAME

		///Footnote
		string strModel, strConclusion;
		//if (vAIC1[3] == vAIC2[3])
			//strModel = "Both Model1 and Model2 are";
		//else
		int nConclusion;
		if (is_equal(vAIC1[3],NANUM) || is_equal(vAIC2[3],NANUM))
		{
			nConclusion = FOOTNOTE_NO_CONCLUSION;
			ocu_load_err_msg_str(XF_FIT_CMP_NO_CONCLUSION, &strCmpConclusion); ///Iris 12/25/2009 QA81-14890-S1 ADD_PREFERED_MODEL_TABLE
		}
		else
		{
			nConclusion = FOOTNOTE_FITCMP_MODEL_AIC1;
		}
		ocu_load_err_msg_str(nConclusion, &strConclusion);
		/// Iris 12/25/2009 QA81-14890-S2 REPLACE_MODEL1_MODEL2_TO_REAL_FUNCTION_NAME
		//strModel = (vAIC1[3] < vAIC2[3]) ? "Model1" : "Model2";
		strModel = (vAIC1[3] < vAIC2[3]) ? strModel1 : strModel2;
		///End REPLACE_MODEL1_MODEL2_TO_REAL_FUNCTION_NAME
		/// Iris 12/25/2009 QA81-14890-S1 ADD_PREFERED_MODEL_TABLE
		if( strCmpConclusion.IsEmpty() )
			strCmpConclusion = strModel;
		///End ADD_PREFERED_MODEL_TABLE
		strConclusion.Format(strConclusion, strModel);
		if (vAIC1[4] != 0 && vAIC2[4] != 0)
		{
			double dMinAICW = (vAIC1[3] < vAIC2[3]) ? vAIC1[4] : vAIC2[4];
			double dMaxAICW = (vAIC1[3] > vAIC2[3]) ? vAIC1[4] : vAIC2[4];
			string strPower;
			ocu_load_err_msg_str(FOOTNOTE_FITCMP_MODEL_AIC2, &strPower);
			strPower.Format(strPower, dMinAICW/dMaxAICW);
			strConclusion += "\n" + strPower;	
		}
		//strConclusion = strModel + " the best-fit model for same dataset";
		TreeNode trFooter = tree_check_get_node(rtAIC, "Footer", IDE_FOOTNOTE_BEGIN, TREE_Footnote, "1"); // just need the TREE_Footnote attribute, value does not matter, so 1 is good
		trFooter.strVal = strConclusion;
		
		///Echo 11/2/07 FOOTNOTE_STYLE_SET_BY_ESCAPE
		//rtRootTable.AddTheme(FITCMP_AIC, trTheme.Root);/// RVD 10/30/2007 v8.0737 qa7-10609 REPORT_FOOTNOTE_STYLE_THEME
		///END FOOTNOTE_STYLE_SET_BY_ESCAPE
		
		/// Iris 12/25/2009 QA81-14890-S1 ADD_PREFERED_MODEL_TABLE
		vector<string> vsConclusion;
		vsConclusion.Add(strCmpConclusion);
		rtModel.AddRow("AIC", vsConclusion, _L("AIC"), vsModelLabels, vsModelTagName, nPreferedModelTableID++); 
		///End ADD_PREFERED_MODEL_TABLE

	}
	
	
	//////////////////////////////////////////////////////////////////
	// F-test
	//////////////////////////////////////////////////////////////////
	if(bFtest)	
	{
		/// Iris 12/25/2009 QA81-14890-S1 ADD_PREFERED_MODEL_TABLE
		//fitcmp_add_ftest(rtRootTable, dSSR1, dSSR2, DF1, DF2, false);
		fitcmp_add_ftest(rtRootTable, dSSR1, dSSR2, DF1, DF2, false, strModel1, strModel2, &strCmpConclusion);
		
		vector<string> vsConclusion;
		vsConclusion.Add(strCmpConclusion);
		rtModel.AddRow("FTest", vsConclusion, _L("F-Test"), vsModelLabels, vsModelTagName, nPreferedModelTableID++); 
		///End ADD_PREFERED_MODEL_TABLE
		
		
		/*
		if (bSameModel)
		{
			dSSR2 += dSSR1;
			DF2 += DF1;
			
			//--- Iris 01/16/2007 IMPLEMENT_SSR_DF_ON_COMBINED_DATA
			WorksheetPage	wksPage;
			wksPage.Create("origin", CREATE_HIDDEN);
			Worksheet		wks = wksPage.Layers();

			XYRange	drCombined;
			_get_create_combined_data_range(trGUI1, trGUI2, wks, drCombined);
			
			string		strClass;
			trRes1.GetAttribute(STR_ANALYSIS_ATTRIB, strClass);
			
			string		strModel;
			if(trRes1.Notes.Model)
				strModel = trRes1.Notes.Model.strVal;
			
			Tree		trStatsResult;			
			if( _calculate_on_combined_data(strClass, drCombined, trStatsResult, strModel) )
			{			
				dSSR1 = trStatsResult.SSR.dVal;			
				DF1 = trStatsResult.DOF.dVal;
			}
			
			wksPage.Destroy();
			/end IMPLEMENT_SSR_DF_ON_COMBINED_DATA
		}
		*/
		///Echo 11/2/07 FOOTNOTE_STYLE_SET_BY_ESCAPE
		//rtRootTable.AddTheme(FITCMP_FTEST, trTheme.Root);/// RVD 10/30/2007 v8.0737 qa7-10609 REPORT_FOOTNOTE_STYLE_THEME
		///END FOOTNOTE_STYLE_SET_BY_ESCAPE
	}
	
	
	//////////////////////////////////////////////////////////////////
	// Fit Parameters
	//////////////////////////////////////////////////////////////////
	if (bFitParams)
	{
		/// Iris 12/25/2009 QA81-14890-S2 REPLACE_MODEL1_MODEL2_TO_REAL_FUNCTION_NAME
		//fitcmp_add_fit_params(rtRootTable, trRes1, trRes2, false);
		fitcmp_add_fit_params(rtRootTable, trRes1, trRes2, false, strModel1, strModel2);
		///End REPLACE_MODEL1_MODEL2_TO_REAL_FUNCTION_NAME
	}
	//////////////////////////////////////////////////////////////////
	// Fit Statistics
	//////////////////////////////////////////////////////////////////
	if (bFitStats)
	{
		/// Iris 12/25/2009 QA81-14890-S2 REPLACE_MODEL1_MODEL2_TO_REAL_FUNCTION_NAME
		//fitcmp_add_fit_stats(rtRootTable, trRes1, trRes2, false);
		fitcmp_add_fit_stats(rtRootTable, trRes1, trRes2, false, strModel1, strModel2);
		///End REPLACE_MODEL1_MODEL2_TO_REAL_FUNCTION_NAME
	}
}


void fitcmpmodel(const Range& result1, const Range& result2, const int& aic, const int& ftest, const int& param, const int& statics, ReportTree& rt)
{
	
	vector<string> vsReportTree;
	Tree		tr;
	TreeNode	trRes1 = tr.AddNode("Res1");
	TreeNode	trRes2 = tr.AddNode("Res2");
	Tree	trGUI1, trGUI2;
	if (!fitcmp_get_rt(result1, trRes1, trGUI1) || !fitcmp_get_rt(result2, trRes2, trGUI2))
		XF_THROW(CER_FITCMP_MODEL_INVALID_RT);
	
	vector<string> vstrFitReport(2);
	result1.GetRangeString(vstrFitReport[0]);
	result2.GetRangeString(vstrFitReport[1]);
	
	_fitcmp_model_update_report_tree(rt, trRes1, trRes2, trGUI1, trGUI2, vsReportTree[0], vsReportTree[1], ftest, aic, param, statics, vstrFitReport);
	
}

//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 fitcmpmodel_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return fitcmpmodel_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	int nErr = fitcmp_event(trGetN, false);
	if(nErr != CER_NO_ERROR)
	{
		bOKEnable = false;
		strErrMsg = nErr;
	}
	
	return true;
	

}

int fitcmpmodel_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 fitcmpmodel_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 fitcmpmodel_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
