#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	missing_pairwise,
	missing_listwise,
};


#include <ReportTree.h>
#include <GetNBox.h>
#include <report_utils.h>
#include <event_utils.h>
#include  <stats_utils.h>
#include <..\Originlab\XFunctionEx.h>
#include <o8dlg.h>
//put additional include files here
///////////////////////////////////////////////////
// Modification log
///Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT
///Max 3/7/08 SHOULD_PASS_WHOLE_STRING_OF_LPCSZRDLABEL_FOR_LOCALIZATION
///Max 3/19/08 SHOULD_NOT_RESET_VARIABLE_VALUE_IN_LT
///Kyle 12/18/2008 ADD_MESSAGE_TO_DISCRIBE_SIGNIFICANCE_RESULT_FOR_CORRELEATION_COEFFICIENT
///Kyle 01/05/2009 CORR_OUTPUT_MESSAGE_ABOUT_COLUMNS_MISSING_VALUES
///Kyle 04/14/2009 FIX_OUTPUT_INVALID_ACCESS_FROM_LT
///Jacky 08/27/10 ORG-920-P3 ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
///////////////////////////////////////////////////

//put your own support static functions here


#define	ELLIPSE_CURVE	 		200
#define CORR_MAX_GROUP			1000
#define CORR_MIN_POINTS			2
#define STR_XF_NAME				"plotmatrix"
///Kyle 12/18/2008 ADD_MESSAGE_TO_DISCRIBE_SIGNIFICANCE_RESULT_FOR_CORRELEATION_COEFFICIENT
//void corr_coef_update_report_table(ReportTree& outRT, matrix mPeaCorr, matrix mPeaSig, matrix mSpeCorr, matrix mSpeSig, matrix mKenCorr, matrix mKenSig, vector<string> vstrFactors, int pearson, int spearman, int kendall)
void corr_coef_update_report_table(ReportTree& outRT, matrix mPeaCorr, matrix mPeaSig, matrix mSpeCorr, matrix mSpeSig, matrix mKenCorr, matrix mKenSig, vector<string> vstrFactors, int pearson, int spearman, int kendall, int flag)
///End ADD_MESSAGE_TO_DISCRIBE_SIGNIFICANCE_RESULT_FOR_CORRELEATION_COEFFICIENT
{
	
	if (pearson)
	{
		int nBaseID = IDST_REG_CORR_TABLE;
		///Kyle 12/18/2008 ADD_MESSAGE_TO_DISCRIBE_SIGNIFICANCE_RESULT_FOR_CORRELEATION_COEFFICIENT
		//rt_add_corr_coef_table(outRT, mPeaCorr, mPeaSig, vstrFactors, "PeasonCorr", "Pearson" , nBaseID);
		rt_add_corr_coef_table(outRT, mPeaCorr, mPeaSig, vstrFactors, "PeasonCorr", "Pearson" , nBaseID, flag);
		///End ADD_MESSAGE_TO_DISCRIBE_SIGNIFICANCE_RESULT_FOR_CORRELEATION_COEFFICIENT
		
	}
	if (spearman)
	{
		int nBaseID = IDST_REG_CORR_TABLE + 1;
		///Kyle 12/18/2008 ADD_MESSAGE_TO_DISCRIBE_SIGNIFICANCE_RESULT_FOR_CORRELEATION_COEFFICIENT
		//rt_add_corr_coef_table(outRT, mSpeCorr, mSpeSig, vstrFactors, "SpearCorr", "Spearman" , nBaseID);
		rt_add_corr_coef_table(outRT, mSpeCorr, mSpeSig, vstrFactors, "SpearCorr", "Spearman" , nBaseID, flag);
	}
	
	if (kendall)
	{
		int nBaseID = IDST_REG_CORR_TABLE + 2;
		///Kyle 12/18/2008 ADD_MESSAGE_TO_DISCRIBE_SIGNIFICANCE_RESULT_FOR_CORRELEATION_COEFFICIENT
		//rt_add_corr_coef_table(outRT, mKenCorr, mKenSig, vstrFactors, "KenCorr", "Kendall" , nBaseID);
		rt_add_corr_coef_table(outRT, mKenCorr, mKenSig, vstrFactors, "KenCorr", "Kendall" , nBaseID, flag);
		///End ADD_MESSAGE_TO_DISCRIBE_SIGNIFICANCE_RESULT_FOR_CORRELEATION_COEFFICIENT
	}
	
}


static bool _corr_at_least_1_output(TreeNode& trGetN)
{
	if (trGetN.pearson.nVal || trGetN.spearman.nVal || trGetN.kendall.nVal || trGetN.scatter.nVal)
		return true;
	else
		return false;
}



static int corrcoef_check_input(TreeNode& trGetN)
{
	int nErr;
	nErr = check_input_range(trGetN.irng, trGetN.missing.nVal);
	if (nErr != CER_NO_ERROR)
		return nErr;
		
	if ( !_corr_at_least_1_output(trGetN) && CER_NO_ERROR == nErr)
	{
		nErr = CER_SUPPRESS_ALL_OUTPUT;	
	}
	
	if (!check_conf_level(trGetN.conflevel) && trGetN.conflevel.Enable && CER_NO_ERROR == nErr)
	{
		nErr = CER_INVALID_CONF_LEV; 
	}
	
	return nErr;
}


void corrcoef(const Range& irng, const int& pearson, const int& spearman, const int& kendall, const int& scatter, const int& ellipse, const double& conflevel, const int& missing, ReportData& rd, ReportTree& rtplot, ReportTree& rt, const int& flag)
{
	
	vector<string> vstrFactors;
	matrix mData;
	int nRet;
	///Kyle 01/05/2009 CORR_OUTPUT_MESSAGE_ABOUT_COLUMNS_MISSING_VALUES
	//if (!corr_get_data(irng, mData, vstrFactors, missing))
	vector<string> vstrFactorsMissingVal;
	if (!corr_get_data(irng, mData, vstrFactors, vstrFactorsMissingVal, missing))
	///End CORR_OUTPUT_MESSAGE_ABOUT_COLUMNS_MISSING_VALUES
		XF_THROW(CER_COL_NUM_TOO_FEW);
	
	
	int nRows = mData.GetNumRows();
	int nCols = mData.GetNumCols();
	
	
	LPCSTR lpsczLabel = _L("Correlations Coefficients");
	report_tree_create(rt, lpsczLabel, "irng");
	
	/// *** Add descriptive statistics
	vector vData;
	mData.GetAsVector(vData, false);
	vector vGroup, vSubGroup;
	for (int ii = 0; ii < nCols; ii++ )
	{
		vSubGroup.SetSize(nRows);
		vSubGroup = ii;
		vGroup.Append(vSubGroup);		
	}
	
	
	DescStatResults pDescStats[CORR_MAX_GROUP];
	QuantileResults pQuantiles[CORR_MAX_GROUP];
	desc_stats_group(vData, vGroup, pDescStats, pQuantiles);
	///Kyle 01/05/2009 CORR_OUTPUT_MESSAGE_ABOUT_COLUMNS_MISSING_VALUES
	//rt_add_corr_desc_stats(rt, pDescStats, pQuantiles, vstrFactors);	
	if(vstrFactorsMissingVal.GetSize())
	{
		string strFooter, strCols;
		strCols.SetTokens(vstrFactorsMissingVal, ',');
		strFooter.Format(_L("Empty Columns: %s"), strCols);
		rt_add_corr_desc_stats(rt, pDescStats, pQuantiles, vstrFactors, strFooter);
	}
	else
	{
		rt_add_corr_desc_stats(rt, pDescStats, pQuantiles, vstrFactors);	
	}
	///End CORR_OUTPUT_MESSAGE_ABOUT_COLUMNS_MISSING_VALUES
	
	double* pmPeaCov = NULL;
	double* pmPeaSig = NULL;
	matrix mPeaCorr(nCols, nCols);
	matrix mPeaSig(nCols, nCols);
	if (pearson)
	{
		pmPeaCov = mPeaCorr;
		pmPeaSig = mPeaSig;	
	}
	
	double* pmSpeCov = NULL;
	double* pmSpeSig = NULL;
	matrix mSpeCorr(nCols, nCols);
	matrix mSpeSig(nCols, nCols);
	if (spearman)
	{
		pmSpeCov = mSpeCorr;
		pmSpeSig = mSpeSig;	
	}
	
	double* pmKenCov = NULL;
	double* pmKenSig = NULL;
	matrix mKenCorr(nCols, nCols);
	matrix mKenSig(nCols, nCols);
	if (kendall)
	{
		pmKenCov = mKenCorr;
		pmKenSig = mKenSig;	
	}
	nRet = ocmath_corr_coeff(nRows, nCols, mData, pmPeaCov, pmPeaSig, pmSpeCov, pmSpeSig, pmKenCov, pmKenSig);
	
	/// *** Correlation Coefficient Matrix Computation
	/*
	matrix mPeaCorr(nCols, nCols);
	matrix mPeaSig(nCols, nCols);
	nRet = ocmath_pea_corr_coeff(nRows, nCols, mData, mPeaCorr, mPeaSig, missing);
	if (nRet != STATS_NO_ERROR)
		XF_THROW_EX(CER_UNKNOWN_ERROR_EX, nRet);
	
	matrix mSpeCorr(nCols, nCols);
	matrix mSpeSig(nCols, nCols);
	nRet = ocmath_spe_corr_coeff(nRows, nCols, mData, mSpeCorr, mSpeSig, missing);
	if (nRet != STATS_NO_ERROR)
		XF_THROW_EX(CER_UNKNOWN_ERROR_EX, nRet);
	
	matrix mKenCorr(nCols, nCols);
	matrix mKenSig(nCols, nCols);
	nRet = ocmath_ken_corr_coeff(nRows, nCols, mData, mKenCorr, mKenSig, missing);
	if (nRet != STATS_NO_ERROR)
		XF_THROW_EX(CER_UNKNOWN_ERROR_EX, nRet);
	*/
	///Kyle 12/18/2008 ADD_MESSAGE_TO_DISCRIBE_SIGNIFICANCE_RESULT_FOR_CORRELEATION_COEFFICIENT
	//corr_coef_update_report_table(rt, mPeaCorr, mPeaSig, mSpeCorr, mSpeSig, mKenCorr, mKenSig, vstrFactors, pearson, spearman, kendall);
	corr_coef_update_report_table(rt, mPeaCorr, mPeaSig, mSpeCorr, mSpeSig, mKenCorr, mKenSig, vstrFactors, pearson, spearman, kendall, flag);
	///End ADD_MESSAGE_TO_DISCRIBE_SIGNIFICANCE_RESULT_FOR_CORRELEATION_COEFFICIENT
		
	///*** Add plots
	if (scatter)
	{
		int nFit = 0;
		matrix mFitStat;
		scatter_matrix_update_report_data(mData, vstrFactors, conflevel, ellipse, nFit,rd, mFitStat);
		
		int nPlotCntrl = PLOT_MATTRIX_SCATTER;
		if (ellipse)	nPlotCntrl += PLOT_MATTRIX_ELLIPSE;
		plotmatrix_rd_plotting(rtplot, rd, nCols, mFitStat, nPlotCntrl, vstrFactors)
	
	}	
}

//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 corrcoef_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return corrcoef_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	trGetN.conflevel.Enable = trGetN.ellipse.nVal;
			
	if (1 == trGetN.ellipse.nVal) 
	{
		trGetN.scatter.nVal = 1;
		trGetN.scatter.Enable = 0;
	}else
	{
		trGetN.scatter.Enable = 1;		
	}
	/// Max 3/7/08 SHOULD_PASS_WHOLE_STRING_OF_LPCSZRDLABEL_FOR_LOCALIZATION
	//rd_set_optional(nEventID, bOKEnable, lpcszNodeName, trGetN.rd, trGetN.scatter.nVal, "PlotData1");
	//tr_set_optional(nEventID, lpcszNodeName, trGetN.rtplot, trGetN.scatter.nVal, "[<input>]<new template:=graph name:=ScatterMatrix1>");
	/// Max 4/8/08 move to event_utils.h
	//string strRDvalue = "[<input>]<new>", strRTvalue = "[<input>]<new templat:=graph>";
	//--- 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, strRTvalue = STR_DEFAULT_VALUE_FOR_PLOT_SHEET_NODE;
	string strRTvalue = STR_DEFAULT_VALUE_FOR_PLOT_SHEET_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);
	okutil_convert_localized_PDS(&strRTvalue);
	//tr_set_optional(nEventID, lpcszNodeName, trGetN.rd, trGetN.scatter.nVal, strRDvalue);
	//tr_set_optional(nEventID, lpcszNodeName, trGetN.rtplot, trGetN.scatter.nVal, strRTvalue);
	BOOL	bChangeParam = xf_event_is_change_param(trGetN);
	tr_set_optional_ex(nEventID, lpcszNodeName, trGetN.rd, bChangeParam, trGetN.scatter.nVal);
	tr_set_optional_ex(nEventID, lpcszNodeName, trGetN.rtplot, bChangeParam, trGetN.scatter.nVal,strRTvalue);
	//--- end ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
	/// END SHOULD_PASS_WHOLE_STRING_OF_LPCSZRDLABEL_FOR_LOCALIZATION
	
	int nErr = corrcoef_check_input(trGetN);
	///Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT
	if(CER_NO_ERROR == nErr)
	{
		if(is_same_sheet(trGetN.rd, trGetN.rt) || is_same_sheet(trGetN.rd, trGetN.rtplot) || is_same_sheet(trGetN.rtplot, trGetN.rt))
			nErr = XFERR_REPORT_SHEET_CONFLICT;
	}
	///End REPORT_SHEET_CHECK_CONFLICT
	if (nErr != CER_NO_ERROR)
	{
		strErrMsg = nErr;
		if (nErr == CER_DATA_TOO_FEW)
			strErrMsg += ":" + CORR_MIN_POINTS;
		bOKEnable = false;
	}
		
	return true;	

}

int corrcoef_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 corrcoef_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_corrcoef);
	
	if (1 == trGetN.ellipse.nVal) trGetN.scatter.nVal = 1;
	
	/// Max 3/19/08 SHOULD_NOT_RESET_VARIABLE_VALUE_IN_LT
	// It is the responsibility of users to specify each variable value (<auto> ones are exception) when run from LT
	/*
	///handle case that user select plot but not specify rd and rtPlot, when run from command
	if (nGetNDialog <= 0)
	{
		/// Max 3/7/08 LOCALIZE_PREDEFINED_STRING
		//if (trGetN.rd.strVal.Compare(STR_OPTIONAL) == 0 && trGetN.scatter.nVal == 1)
		//{
			//trGetN.rd.strVal = "[<input>]<new name:=PlotData1>";
			//trGetN.rtplot.strVal = "[<input>]<new template:=graph name:=ScatterMatrix1>";
		//}
		if(compare_string_localization(trGetN.rd.strVal, STR_OPTIONAL) && trGetN.scatter.nVal == 1)
		{
			string strRDvalue = "[<input>]<new>", strRTvalue = "[<input>]<new template:=graph>";
			okutil_convert_localized_PDS(&strRDvalue);
			okutil_convert_localized_PDS(&strRTvalue);
			trGetN.rd.strVal = strRDvalue;
			trGetN.rtplot.strVal = strRTvalue;
		}
		/// END LOCALIZE_PREDEFINED_STRING
	}
	*/
	/// END SHOULD_NOT_RESET_VARIABLE_VALUE_IN_LT
	/// Max 4/8/08 v8.0839 NEED_TO_CHECK_THEME_CHANGE_CASE
	if(nGetNDialog > 0 && trGetN.scatter.nVal == 0)
	{
		trGetN.rd.Enable =false;
		trGetN.rtplot.Enable = false;
	}
	/// END NEED_TO_CHECK_THEME_CHANGE_CASE
	
	///Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT
	//if (CER_NO_ERROR != corrcoef_check_input(trGetN) && (dwCntrl&LTXF_THEME_USED) && nGetNDialog <= 0 )
	if (nGetNDialog <= 0 )
	{
		int nErr = corrcoef_check_input(trGetN);
		if(CER_NO_ERROR == nErr)
		{
			if(is_same_sheet(trGetN.rd, trGetN.rt) || is_same_sheet(trGetN.rd, trGetN.rtplot) || is_same_sheet(trGetN.rtplot, trGetN.rt))
				nErr = XFERR_REPORT_SHEET_CONFLICT;
		}
		if(CER_NO_ERROR != nErr)
		{
			if((dwCntrl&LTXF_THEME_USED))
				nRet = XFEVT_PROCEED_WITH_DLG;	
			else
			{
				warning_msg_box(nErr, false, 'E');
				nRet = XFEVT_ABORT;			
			}
		}
	}
	///End 	REPORT_SHEET_CHECK_CONFLICT
	///Kyle 04/14/2009 FIX_OUTPUT_INVALID_ACCESS_FROM_LT
	string 	strRDvalue = STR_DEFAULT_TEXT_FOR_REPORT_DATA_NODE,
			strRTvalue = STR_DEFAULT_VALUE_FOR_PLOT_SHEET_NODE;
	okutil_convert_localized_PDS(&strRDvalue);
	okutil_convert_localized_PDS(&strRTvalue);
	tr_set_optional(0, "", trGetN.rd, trGetN.scatter.nVal, strRDvalue);
	tr_set_optional(0, "", trGetN.rtplot, trGetN.scatter.nVal, strRTvalue);
	///End FIX_OUTPUT_INVALID_ACCESS_FROM_LT
}
//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 corrcoef_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
