#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
//put additional include files here
/*------------------------------------------------------------------------------*
*	Modification Log:															*
*	Nicole 07/05/2007 v8.0655 REMOVE_SPACE_FOR_LOCATION_STRING					*
*	Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT						*
*	Max 3/7/08 SHOULD_PASS_WHOLE_STRING_OF_LPCSZRDLABEL_FOR_LOCALIZATION		*
*	Jacky 07/22/10 ORG-102 USER_CAN_SET_SIGNIFICANCE_LEVEL						*
*	Jacky 08/27/10 ORG-920-P3 ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
*-------------------------------------------------------------------------------*/
#include <GetNBox.h>
#include <report_utils.h>
#include <event_utils.h>
#include <stats_utils.h>
#include <o8dlg.h>
//put your own support static functions here

//static void _ftest_get_footer(const int nTail, string& strHYPT, string& strFooter1, string& strFooter2)
//{
	//int nHYPT = FOOTNOTE_VARTEST2_TWO_TAIL
	//
	//switch (nTail)
	//{
	//case 0:
	//default:
		//strHYPT = "Null Hypothesis: Variance1/Variance2 = 1 \nAlternative Hypothesis: Variance1/Variance2 <> 1 \n";
		//break;
	//case 1:
		//strHYPT = "Null Hypothesis: Variance1/Variance2 <= 1 \nAlternative Hypothesis: Variance1/Variance2 > 1 \n";
		//break;
	//case 2:
		//strHYPT = "Null Hypothesis: Variance1/Variance2 >= 1 \nAlternative Hypothesis: Variance1/Variance2 < 1 \n";
		//break;
		//
	//}
	//
	//strFooter1 = "At the 0.05 level, the two population variance is not significantly different";
	//strFooter2 = "At the 0.05 level, the two population variance is significantly different";
	//
//}

static void _get_ftest_stats(FVarResults &stFStats, vector &vFStats)
{
	vFStats.SetSize(4);
	vFStats[0] = stFStats.FValue;
	vFStats[1] = stFStats.FDOFNum;
	vFStats[2] = stFStats.FDOFDen;
	vFStats[3] = stFStats.FProb;	
	
}

void _rt_add_ftest_stats(ReportTree& outRT, const vector& vFStats, const vector<string>& vstrGroup, const string& strFootNote)
{
	ReportTable rtFStats = outRT.CreateTable("Stats", _L("F Statistics"), IDST_T_TEST_RESULT);
	
	vector<string> vstrFStatsLabels, vstrFTagName;
	vstrFStatsLabels.SetSize(4);
    vstrFStatsLabels[0] = _L("F");
	vstrFStatsLabels[1] = _L("Numer. DF");
	vstrFStatsLabels[2] = _L("Denom. DF");
	vstrFStatsLabels[3] =  _L("Prob > F");
	
	string str = F_TEST_STATS;
	str.GetTokens(vstrFTagName, '|');
	vstrFTagName.InsertAt(0, "F");
	
	/// Nicole 07/05/2007 v8.0655 REMOVE_SPACE_FOR_LOCATION_STRING
	//rtFStats.AddRow(_L(""),vFStats, _L(" "), vstrFStatsLabels, NULL, IDST_T_TEST_RESULT+1);
	rtFStats.AddRow("Ftest", vFStats, " ", vstrFStatsLabels, vstrFTagName, IDST_T_TEST_RESULT+1);
	/// End REMOVE_SPACE_LOCATION_STRING

	///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
	TreeNode trRow = rtFStats.GetNode("Ftest");
	if ( trRow )
		tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y);
	///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES

	//string strResult, strFootNote;
	//if(vFStats[0] >= 0.05) strResult = strFooter2;
	//else strResult = strFooter1;
//
	//strFootNote = strHYPT + strResult;
	TreeNode trFooter = tree_check_get_node(rtFStats, "Footer", IDE_FOOTNOTE_BEGIN, TREE_Footnote, "1"); // just need the TREE_Footnote attribute, value does not matter, so 1 is good
	trFooter.strVal = strFootNote;		
}

static void _set_desc_stats_opt(DescStatOptions& stDescOpt)
{
	stDescOpt.N = true;
	stDescOpt.Mean = true;
	stDescOpt.SD = true;
	stDescOpt.Variance = true;	
}



void TwoSampleTestVar(const string& hint_indexed, const string& hint_raw, const int& type, const Range& irng, const string& null, const int& tail, const double& alpha, const int& conf, const string& level, const int& histogram, const int& box, ReportData& rd, ReportTree& rt)
{
	
	int nMissing, nRet;
	vector vData1, vData2;
	vector<string> vstrLab;
	
	nRet = (0 == type)? get_2_data_in_group(irng, vData1, vData2, vstrLab, nMissing) : get_2_data_in_var(irng, vData1, vData2, vstrLab, nMissing);	
	if (nRet != STATS_NO_ERROR)			
		XF_THROW(nRet);
						
	int nSize1 = vData1.GetSize();
	int nSize2 = vData2.GetSize();
	
	
	/// *** Descriptive Statistics
	DescStatOptions stStatsOpt;
	_set_desc_stats_opt(stStatsOpt);
	
	DescStatResults pDescStats[2];
	nRet = stats_desc_stats(vData1, stStatsOpt, pDescStats[0]);
	if (nRet != STATS_NO_ERROR)
	{
		XF_THROW_EX(CER_UNKNOWN_ERROR_EX, nRet);
	}
	nRet += stats_desc_stats(vData2, stStatsOpt, pDescStats[1]);
	if (nRet != STATS_NO_ERROR)
	{
		XF_THROW_EX(CER_UNKNOWN_ERROR_EX, nRet);
	}
		
	LPCSTR lpsczLabel = _L("Two-Sample Test for Variance");
	report_tree_create(rt, lpsczLabel, "irng");	
	
	DescStatOptions stDescOpt;	
	rt_add_desc_stats(rt, &stStatsOpt, NULL, pDescStats, NULL, vstrLab);
		//
	///// *****		Two sample f test		***** ///							 
	HypotTestOptions opt;
	FVarResults stFRes;
	opt.HypotValue = 1;
	opt.TailType=tail;
	nRet = ocmath_f_test(nSize1, vData1, nSize2, vData2, &opt, &stFRes);
	if (nRet != STATS_NO_ERROR)
	{
		XF_THROW_EX(CER_UNKNOWN_ERROR_EX, nRet);
	}
	//
	//string strHYPT, strFooter1, strFooter2;
	//_ftest_get_footer(tail, strHYPT, strFooter1, strFooter2);
	string strHYPT, strConclusion;
	int nHYPT, nConclusion, nConAccept, nConReject;
	switch (tail)
	{
		case TAILED_TEST_TWO:
		default:
			nHYPT = FOOTNOTE_VARTEST2_TWO_TAIL;
			nConAccept = FOOTNOTE_VARTEST2_CON_DIFF;
			nConReject = FOOTNOTE_VARTEST2_CON_SAME;
			break;
		case TAILED_TEST_UPPER:
			nHYPT = FOOTNOTE_VARTEST2_UPPER_TAIL;
			nConAccept = FOOTNOTE_VARTEST2_CON_GRT;
			nConReject = FOOTNOTE_VARTEST2_CON_NOT_GRT;
			break;
		case TAILED_TEST_LOWER:
			nHYPT = FOOTNOTE_VARTEST2_LOWER_TAIL;
			nConAccept = FOOTNOTE_VARTEST2_CON_LES;
			nConReject = FOOTNOTE_VARTEST2_CON_NOT_LES;
			break;
	}
	
	ocu_load_err_msg_str(nHYPT, &strHYPT);
	//--- Jacky 07/22/10 ORG-102 USER_CAN_SET_SIGNIFICANCE_LEVEL
	//nConclusion = (stFRes.FProb < 0.05) ? nConAccept : nConReject;
	nConclusion = (stFRes.FProb < alpha) ? nConAccept : nConReject;
	//--- end USER_CAN_SET_SIGNIFICANCE_LEVEL
	ocu_load_err_msg_str(nConclusion, &strConclusion);
	//--- Jacky 07/22/10 ORG-102 USER_CAN_SET_SIGNIFICANCE_LEVEL
	strConclusion.Format(strConclusion,alpha);
	//--- end USER_CAN_SET_SIGNIFICANCE_LEVEL
	strConclusion = strHYPT + strConclusion;
	vector vFStats;
	_get_ftest_stats(stFRes, vFStats);
	_rt_add_ftest_stats(rt, vFStats, vstrLab, strConclusion);
	
	if (conf)
	{
		vector vLevels, vPercents;
		int nLevels = level.GetTokens(vPercents);//put the confidence levels in vector
		vLevels = vPercents / 100.0;
		
		vector vLCLs, vUCLs;
		vLCLs.SetSize(nLevels);
		vUCLs.SetSize(nLevels);
															 
		vector vSD(2);
		vSD[0] = pDescStats[0].SD;
		vSD[1] = pDescStats[1].SD;
		
		vector<int> vN(2);
		vN[0] = pDescStats[0].N;
		vN[1] = pDescStats[1].N;
																
		nRet = ocmath_two_sample_confidence_levels_for_variance(vLevels.GetSize(), vLevels, vSD, vN, vLCLs, vUCLs);
		if (nRet != STATS_NO_ERROR)
		{
			XF_THROW_EX(CER_UNKNOWN_ERROR_EX, nRet);
		}
		
		rt_add_conf_intvl(rt, vPercents, vLCLs, vUCLs, _L("Variances"));
	}
	
	if (rd)
	{
		vector vLevInGroup(2);
		vLevInGroup[0] = vData1.GetSize();
		vLevInGroup[1] = vData2.GetSize();
		vector vData;
		vData = vData1;
		vData.Append(vData2);
		
		ttest_update_report_data(rd, vData,vLevInGroup,vstrLab);
		
		int nPlotType; 
		if ( histogram ) nPlotType += HYPO_TEST_HISTOGRAM;
		if ( box ) nPlotType += HYPO_TEST_BOX;
		
		hypo_test_rd_plotting(rd, vstrLab, nPlotType, rt);
	}
	
}

//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 TwoSampleTestVar_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return TwoSampleTestVar_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	int nType = trGetN.type.nVal;
	switch( nType )
	{
	case 0:
		tree_stats_convert_input_data(trGetN.irng, SIDT_INGROUP);
		break;
	
	case 1:
		tree_stats_convert_input_data(trGetN.irng, SIDT_INVAR);
		break;
	}
	
	//Report Data Only enable if plot is selected
	/// Max 3/7/08 SHOULD_PASS_WHOLE_STRING_OF_LPCSZRDLABEL_FOR_LOCALIZATION
	//rd_set_optional(nEventID, bOKEnable, lpcszNodeName, trGetN.rd, trGetN.box.nVal || trGetN.histogram.nVal, "PlotData1");
	/// Max 4/8/08 move to event_utils.h
	//string strRDvalue = "[<input>]<new>";
	//--- Jacky 08/27/10 ORG-920-P3 ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
	//string strRDvalue = STR_DEFAULT_TEXT_FOR_REPORT_DATA_NODE;
	//--- end ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
	//------
	//--- Jacky 08/27/10 ORG-920-P3 ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
	//okutil_convert_localized_PDS(&strRDvalue);
	//tr_set_optional(nEventID, lpcszNodeName, trGetN.rd, trGetN.box.nVal||trGetN.histogram.nVal, strRDvalue);
	tr_set_optional_ex(nEventID, lpcszNodeName, trGetN.rd, xf_event_is_change_param(trGetN), trGetN.box.nVal || trGetN.histogram.nVal);
	//--- end ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
	/// END SHOULD_PASS_WHOLE_STRING_OF_LPCSZRDLABEL_FOR_LOCALIZATION
	
	int nErr = (0 == nType) ? check_2_data_in_group(trGetN.irng) : check_2_data_in_var(trGetN.irng);
	if (nErr != CER_NO_ERROR)
	{
		strErrMsg = nErr;
		bOKEnable = false;
	}	
	///Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT
	//return ttest_event(trGetN, bOKEnable, strErrMsg, _L("Variance 1/Variance 2"));	
	bool bRet = ttest_event(trGetN, bOKEnable, strErrMsg, _L("Variance 1/Variance 2"));	
	if(bOKEnable && is_same_sheet(trGetN.rd, trGetN.rt))
	{
		bOKEnable = false;
		nErr = XFERR_REPORT_SHEET_CONFLICT;
		strErrMsg = nErr;
	}
	return bRet;
	///End REPORT_SHEET_CHECK_CONFLICT	
	

}

int TwoSampleTestVar_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 TwoSampleTestVar_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	//------ fisher 11/16/07 ADD_MAP_ID_TO_CHM
	if(is_use_origin_chm())
		trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_XF_TwoSampleTestVar);
	
	///Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT
	//if ((dwCntrl&LTXF_THEME_USED) && nGetNDialog <= 0)
	if (nGetNDialog <= 0)
	{
		int nErr;
		bool bOKEnable; 
		string strErrMsg;
		ttest_event(trGetN, bOKEnable, strErrMsg, _L("Variance 1/Variance 2"));
		//if (CER_NO_ERROR != check_1_data(trGetN.irng, true) ||  strErrMsg != "")
		if(strErrMsg.IsEmpty() && CER_NO_ERROR == nErr)
		{
			nErr = check_1_data(trGetN.irng, true);
			if(CER_NO_ERROR == nErr && is_same_sheet(trGetN.rd, trGetN.rt))
				nErr = XFERR_REPORT_SHEET_CONFLICT;
		}
		if(!strErrMsg.IsEmpty() || CER_NO_ERROR != nErr)
		{
			if((dwCntrl&LTXF_THEME_USED))
				nRet = XFEVT_PROCEED_WITH_DLG;		
			else
			{
				if(strErrMsg.IsEmpty())
					warning_msg_box(nErr, false, 'E');
				else
					warning_msg_box(strErrMsg, false, 'E');
				nRet = XFEVT_ABORT;
			}
		}
	}
	///End REPORT_SHEET_CHECK_CONFLICT
}
//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 TwoSampleTestVar_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
