/*------------------------------------------------------------------------------*
 * File Name:				 													*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * CPY 8/11/06 REMOVE_RM_TO_AVOID_LOAD_PROBLEM									*
 *	CPY 10/14/06 SEPARATE_OUT_OPERATION_BASE_INTO_SEPARATE_HEADER				*
 *	Echo 2/7/07 ADD_ERROR_REPORT												*
 *  Iris 05/25/2007 v8.0627 HIDE_BOX_CHART_IN_SR0_TEMP							*
 *	Cheney 2007-6-7 SHOULD_CHECK_EVENT_ID_IN_EVENT_FUNC							*
 *	Arvin 09/07/07 SHOULD_ALWAYS_ADD_STATISTICS_TABLE							*
 *	Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO*
 *	Arvin 02/14/08 QA70-11094 SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
 *	Sophy 10/21/2008 QA80-12000-P2 ANOVAONEWAY_RM_DONT_SUPPORT_REPORT_MASKED_AND_MISSING_DATA
 *	Jacky 07/22/10 ORG-102 USER_CAN_SET_SIGNIFICANCE_LEVEL						*
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// Including the system header file Origin.h should be sufficient for most Origin
// applications and is recommended. Origin.h includes many of the most common system
// header files and is automatically pre-compiled when Origin runs the first time.
// Programs including Origin.h subsequently compile much more quickly as long as
// the size and number of other included header files is minimized. All NAG header
// files are now included in Origin.h and no longer need be separately included.
//
// Right-click on the line below and select 'Open "Origin.h"' to open the Origin.h
// system header file.
#include <Origin.h>
#include <event_utils.h>
#include <report_utils.h>

#ifdef _FOR_SMART_LOADING_ONLY
#include "wksOperation.h" //---- CPY 10/14/06 SEPARATE_OUT_OPERATION_BASE_INTO_SEPARATE_HEADER
#include <analysis_utils.h>
#include <stats_utils.h>
#include "stats_guis.h"
#include "stats_operations.h"
#include "nlsf_utils.h" /// Iris 7/08/2008 CLEAN_DUP_CALC_AVE_DATA_CODE_IN_NLSF_PREVIEW_AND_OP
#include "graph_utils.h" //---- Iris 11/19/2008 v8.0975 QA80-12591-P2 FIX_APPARENT_FIT_ON_GRAPH_CUSTOM_RANGE_GET_INCORRECT_X
#endif

#include <xfutils.h>	///Echo 2/7/07 ADD_ERROR_REPORT
#include <statEx_utils.h>
#include "StatsOpCommon.h"
#include "StatsOpBase.h"
#include "ANOVAOneWay.h"
#include "ANOVAOneWayRM.h" //CPY 8/11/06 REMOVE_RM_TO_AVOID_LOAD_PROBLEM	

////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////
// Include your own header files here.


////////////////////////////////////////////////////////////////////////////////////
// Start your functions here.

///Echo 2/7/07 ADD_ERROR_REPORT
static int check_anovarm_data(Range& rData)
{
	DWORD		dwRules = DRR_RM_ANOVA;
	Worksheet	wksTemp;
	int nn = rData.GetNumData(dwRules, NULL, &wksTemp, NULL, NULL);
	if (nn == -98 || nn == -97)
	{
		return CER_NOT_1_DATA_PER_CELL;
	}
	if (nn <= 0)
	{
		return CER_NOT_RM_ANOVA_DATA;
	}	
	
	matrix		mData;
	int			nOutcome, numFactorVals;
	nn = rData.GetDataRMOneWayANOVA(dwRules, nOutcome, numFactorVals, &mData, NULL);
	switch (nOutcome)
	{
	case RMDATA_ERR_ONE_WAY_MISSING_VALUES_FOUND:
	case RMDATA_ERR_ONE_WAY_GENERAL_ILLEGAL_DATA:
		return CER_NOT_1_DATA_PER_CELL;
		break;
	case RMDATA_ERR_ONE_WAY_MISSING_SUBJECT_DATA:
		return CER_NOT_RM_ANOVA2_DATA;	
	}
	if (nn < 0 )	
	{
		return CER_NOT_RM_ANOVA_DATA;
	}
	if (mData.GetNumRows() < ANOVA2_MIN_FACTOR_SUBJECT || mData.GetNumCols() < ANOVA2_MIN_FACTOR_SUBJECT)
	{
		return CER_TO_FEW_FACTOR;
	}
				
	return CER_NO_ERROR;

}
static int anovaonewayrm_event1(TreeNode& tr, int nRow, int nEvent, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& getNCountainer, string& strAux, string& strErrMsg)
{
	DECLARE_BUTTON_ENABLES   //support more buttons enable/disable
	
	///Cheney 2007-6-7 SHOULD_CHECK_EVENT_ID_IN_EVENT_FUNC	
	///Cheney 2007-7-6 SHOULD_CHECK_ERR_WHEN_THEME_CHANGE_ALSO
	//if(GETNE_ON_VALUE_CHANGE == nEvent  || GETNE_ON_INIT == nEvent)
	if(GETNE_ON_VALUE_CHANGE == nEvent  || GETNE_ON_INIT == nEvent || GETNE_ON_THEME == nEvent)
	///end SHOULD_CHECK_ERR_WHEN_THEME_CHANGE_ALSO
	///end SHOULD_CHECK_EVENT_ID_IN_EVENT_FUNC
	{
		DataRange drData;
		drData.Create();
		bool bRaw = tr.InputData.Use;
		int nOption = bRaw ? DRTREE_ANOVA_ONE_WAY_RAW : DRTREE_ANOVA_ONE_WAY_INDEXED;
		drData.SetTree(tr.InputData, nOption);
		int nLevels;
		if (tr.InputData.Factor0.Levels) nLevels = tr.InputData.Factor0.Levels.GetNodeCount();
		int nErr = bRaw ? check_data_in_var(drData, nLevels, true) : check_anovarm_data(drData);
		
		int nRaw = tr.InputData.Use;
		
		/// Iris 05/10/2007 v8.0615 REMOVE_BRANCH_CHECK_BOX
		//if ( tr.MeansComp.Use && !check_sig_level( tr.MeansComp.SigLevel.dVal) )
		//--- Jacky 07/22/10 ORG-102 USER_CAN_SET_SIGNIFICANCE_LEVEL 
		if(CER_NO_ERROR == nErr && !check_sig_level(tr.alpha.dVal))
		{
			nErr = CER_INVALID_SIG_LEV;
		}
		//--- end USER_CAN_SET_SIGNIFICANCE_LEVEL
		int nCount = 0;
		foreach(TreeNode trN in tr.MeansComp.Children)
		{
			if(trN.ID == TRGP_CHECK && 0 != trN.nVal)
			{
				nCount++;
			}
		}
		if(0 != nCount && !check_sig_level( tr.MeansComp.SigLevel.dVal) )
		///end REMOVE_BRANCH_CHECK_BOX
		{
			nErr = CER_INVALID_SIG_LEV;
		}
		
		///Sophy 4/11/2008 CHECK_REPORT_DATA_BOOK_NAME_DIFFERENT
		string strRet = "";
		if( CER_NO_ERROR == nErr )
		{
			nErr = check_report_book_curve_book( tr, strRet);
		}
		///end CHECK_REPORT_DATA_BOOK_NAME_DIFFERENT
		if (nErr != CER_NO_ERROR)
		{
			bOKEnable = false;
			strErrMsg = nErr;
			///Sophy 4/14/2008 ADD_OUTPUT_ERR_STRING
			if( !strRet.IsEmpty() )
				strErrMsg += ":" + strRet; 
			///end ADD_OUTPUT_ERR_STRING
		}
		
		/// Iris 5/27/2008 UPDATE_REPORT_BOOK_SHEET_COMBO_ON_SOURCE_CHANGE, if source book/sheet changed, source book/sheet name should update relative
		#ifdef _MOVE_FIT_OUTPUT_TO_OC_CLASS 
		OutputGUIManagerBase* 	pOutputManager = get_output_GUI_manager_pointer(tr);
		if(pOutputManager)
			pOutputManager->UpdateOutputOnDataChange(tr);
		#endif //_MOVE_FIT_OUTPUT_TO_OC_CLASS
		///end UPDATE_REPORT_BOOK_SHEET_COMBO_ON_SOURCE_CHANGE

	}
	return true;
	

}

//virtual 
PEVENT_GETN ANOVAOneWayRM::GetNewEventFunction()
{
	return anovaonewayrm_event1;
}
///end ADD_ERROR_REPORT

void 	ANOVAOneWayRM::ConstructOutputTable(TreeNode& trOperation)
{	
	TreeNode 	trOut = trOperation.Calculation; 
	
	trOut.MultiTest.ID = IDST_RM_ANOVA_MULTI_TEST;
	trOut.SphericityTest.ID = IDST_RM_ANOVA_SPHERICITY_TEST;	
	trOut.ANOVAWS.ID = IDST_RM_ANOVA_WS_ANOVA;
	trOut.ANOVABS.ID = IDST_RM_ANOVA_BS_ANOVA;
	trOut.Statistics.ID = IDST_RM_ANOVA_DEST_STATS;
	trOut.MeansComp.ID = IDST_RM_ANOVA_MEAN_COMP;
	
}

int    ANOVAOneWayRM::ExtractIndexedData(TreeNode &trOp, DataRange& dr, matrix& mData, int& nSizeSubject, int& nSizeFactor, int& nSizeFactor2)
{
	DWORD			dwRules = GetDataRules(trOp);
	Worksheet		wksFirstRange;
	int nn = dr.GetNumData(dwRules, NULL, &wksFirstRange, NULL, NULL);
	if (nn <= 0)
	{
		return -1;
	}	
	
	int			nOutcome, numFactorVals;
	vector<string>	vstrFactorVals;
	nn = dr.GetDataRMOneWayANOVA(dwRules, nOutcome, numFactorVals, &mData, &vstrFactorVals);
	if (nn < 0 || nOutcome < 0)	
	{
		return -2;
	}
	
	GetFactors(trOp);
	m_vsFactors = vstrFactorVals;
	
	nSizeFactor = mData.GetNumCols();
	nSizeSubject = mData.GetNumRows();
	
	return 0;
}


bool	ANOVAOneWayRM::CalcOneData(TreeNode &trOp, int nSizeSubject, int nSizeFactor, int& nSizeFactor2)
{	
	double 		dAlpha = trOp.GUI.MeansComp.SigLevel.dVal;
	
	int 			ncntrl;
	MeanCompMethod 	stMethods;
	GetMeanCompMethod(trOp, stMethods, ncntrl);
	
	RMANOVADescStats* 	pDescStats;
	uint 				nSizeDescStat = nSizeFactor;
	pDescStats = (RMANOVADescStats*)calloc(nSizeDescStat, sizeof(RMANOVADescStats));
	
	RMANOVAOneWay 		RMANOVATable;
	
	MeanCompStats*		pMeanCompStats;
	uint 				nSizeMeanComp = GetMeanCompTableSize(&nSizeFactor);	
	pMeanCompStats = (MeanCompStats*)calloc(nSizeMeanComp, sizeof(MeanCompStats));
	
	MultiTestTable 		RVMultiStats;
	SphericityStats 	RVSphericStats;
	EpsilonStats 		RVEpsilonStats;
	
	int nRet = stats_rm_anova_one_way(stMethods, m_vData, nSizeSubject, nSizeFactor, dAlpha, ncntrl, 
									pDescStats, nSizeDescStat,
									&RMANOVATable,
									pMeanCompStats, nSizeMeanComp,
									&RVMultiStats, &RVSphericStats, &RVEpsilonStats);
	///Cheney 2007-5-21 NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
	CheckANOVARMErr(nRet);
	///end NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
									
	bool 	bRtn;
	if( NAG_ANOVA_RM_NO_ERR == nRet || 
		NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MAUCHLY_TEST == nRet ||
		NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MULTI_TEST == nRet ||
		NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MAUCHLY_OR_MULTI_TEST == nRet )
	{
		bRtn = true;
		
		//--Multi Test table
		if(NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MULTI_TEST != nRet && 
			NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MAUCHLY_OR_MULTI_TEST != nRet)
		{
			AddMultiTestTable(trOp, RVMultiStats);
		}
		else
		{
			AddMultiTestErrorTable(trOp);
		}
				
		//--Mauchly's Test table
		bool bWarnning = false;
		if(NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MAUCHLY_TEST == nRet || 
			NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MAUCHLY_OR_MULTI_TEST == nRet)
		{		
			bWarnning = true;
		}
		AddSphericityTestTable(trOp, RVSphericStats, RVEpsilonStats, bWarnning);
		
		
		//-- add ANOVA table
		RMANOVARow*		pstRMANOVARows;
		UINT 			nSize = RMANOVAONEWAY_LAST_ITEM;		
		pstRMANOVARows = (RMANOVARow*)calloc(nSize, sizeof(RMANOVARow));	
		for(int ii=0; ii<nSize; ii++)
		{
			pstRMANOVARows[ii] = RMANOVATable.AnovaTable[ii];
		}
		AddANOVATable(trOp, pstRMANOVARows, nSize);
		free(pstRMANOVARows);
	
		TreeNode	trTable;
		///Arvin 09/07/07 SHOULD_ALWAYS_ADD_STATISTICS_TABLE
		/*
		if(trOp.GUI.DescStats.nVal)
		{
			trTable = tree_check_get_node(trOp.Calculation, "Statistics", IDST_RM_ANOVA_DEST_STATS, STR_LABEL_ATTRIB, TABLE_RM_DEST_STATS);
			AddDestStatsTable(trOp, trTable, pDescStats, nSizeDescStat, m_vsFactors);
		}
		else
			trOp.Calculation.Statistics.Show = false;
		*/
		bool bShowStats = trOp.GUI.DescStats.nVal;
		//trTable = tree_check_get_node(trOp.Calculation, "Statistics", IDST_RM_ANOVA_DEST_STATS, STR_LABEL_ATTRIB, _L(TABLE_RM_DEST_STATS));
		trTable = tree_check_get_node(trOp.Calculation, "Statistics", IDST_RM_ANOVA_DEST_STATS, STR_LABEL_ATTRIB, TABLE_RM_DEST_STATS);
		AddDestStatsTable(trOp, trTable, pDescStats, nSizeDescStat, m_vsFactors);
		trTable.Show = bShowStats;
		///end SHOULD_ALWAYS_ADD_STATISTICS_TABLE
		
		/// Iris 05/10/2007 v8.0615 REMOVE_BRANCH_CHECK_BOX
		//int nTables, nMeansTable = trOp.GUI.MeansComp.Use;
		//if(nMeansTable)
		int	nTables;
		////end REMOVE_BRANCH_CHECK_BOX
		{
			//trTable = tree_check_get_node(trOp.Calculation, "MeansComp", IDST_RM_ANOVA_MEAN_COMP, STR_LABEL_ATTRIB, _L(TABLE_RM_MEAN_COMP));
			trTable = tree_check_get_node(trOp.Calculation, "MeansComp", IDST_RM_ANOVA_MEAN_COMP, STR_LABEL_ATTRIB, TABLE_RM_MEAN_COMP);
			nTables = AddMeanComparisonTable(trOp, trTable, pMeanCompStats, nSizeMeanComp, nSizeFactor, m_vsFactors);
		}
		/// Iris 05/10/2007 v8.0615 REMOVE_BRANCH_CHECK_BOX
		//if(0 == nMeansTable || 0 == nTables)
		if(0 == nTables)
		///end REMOVE_BRANCH_CHECK_BOX
			trOp.Calculation.MeansComp.Show = false;
		
			
	}
	else
		bRtn = false;
	
	free(pDescStats);
	free(pMeanCompStats);

	/// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	///Arvin 01/31/08 WRONG_GRAPH_TABLES_PLACE
	//In order to keep consistent with OneWayANOVA, we always add Bar Chart, Mean SD and SE, Mean Comparision
	//tables to the last branch of result curves.
	//AddReportCurveTables(trOp, 1, m_strFactor);
	AddReportCurveTables(trOp, m_vsFactors.GetSize(), m_strFactor);
	///END WRONG_GRAPH_TABLES_PLACE
	///end NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	
	return bRtn;
}

string ANOVAOneWayRM::GetClassName()
{
	return "ANOVAOneWayRM";
}

/// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
int ANOVAOneWayRM::ConstructGraphNumber()
{
	return 5;
}

///Arvin 02/14/08 QA70-11094 SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
//DWORD ANOVAOneWayRM::GetOutputOptions()
DWORD ANOVAOneWayRM::GetOutputOptions(const TreeNode& trOp)
///end SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
{
	DWORD 	dwOptions = REPORT_ARRANGE_GRAPHS_TO_COLS | REPORT_PLOT_ALL_PLOTS_IN_ONE_GRAPH;
	return dwOptions;
}


//virtual 
int	ANOVAOneWayRM::GetNumberLayersInOneGraph(TreeNode& trOp, int nGraphIndex)
{
	return 1;
}

int ANOVAOneWayRM::GetResultCurvesID() 
{ 
	return IDST_REPORT_CURVE_OPTIONS;
}

//virtual 
void ANOVAOneWayRM::FilterStatsGUI(TreeNode& trOp) 
{
	ANOVARMReportOperation::FilterStatsGUI(trOp);
	
	// Not SD value in Statistics table, so cannot plot Mean/SD data.
	trOp.GUI.Plots.Graph3.nVal = 0;
	trOp.GUI.Plots.Graph3.Show = false;
	
	/// Iris 05/25/2007 v8.0627 HIDE_BOX_CHART_IN_SR0_TEMP
	trOp.GUI.Plots.Graph2.nVal = 0;
	trOp.GUI.Plots.Graph2.Show = false;	
	///end HIDE_BOX_CHART_IN_SR0_TEMP
	///Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	//As max said, Checkbox PlotInOneGraph only work for Histogram and Boxchart, and this tools has not 
	//the two type graph, so I hide tree node PlotInOneGraph
	/// Iris 10/29/2009 QA81-14546 OP_DLG_NEW_STRUCTURE
	//TreeNode trPlotInOneGraph = trOp.GUI.Output.PlotSettings.PlotInOneGraph;
	TreeNode trPlotInOneGraph = OP_GUI_GRAPH_ARRANGEMENT_NODE(trOp.GUI).PlotInOneGraph;
	///end OP_DLG_NEW_STRUCTURE
	if(trPlotInOneGraph)
		trPlotInOneGraph.Show = false;
	///end UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	///Sophy 10/21/2008 QA80-12000-P2 ANOVAONEWAY_RM_DONT_SUPPORT_REPORT_MASKED_AND_MISSING_DATA should hide checkboxed on GUI Sophy 1/9/2009 centralized to base class
	//trOp.GUI.Output.Create.MaskedData.Show = false;
	//trOp.GUI.Output.Create.MissingData.Show = false; 
	///end ANOVAONEWAY_RM_DONT_SUPPORT_REPORT_MASKED_AND_MISSING_DATA
}
///end NEED_REPORT_PLOTS_IN_RM_ONE_WAY

///Cheney 2007-9-28 MODIFY_TITLE_AS_MAX_SAID
string ANOVAOneWayRM::GetDlgDescription(int nOption)
{
	return _L("Perform Balance One-Way Repeated Measures ANOVA");
}
///end MODIFY_TITLE_AS_MAX_SAID

///Cheney 2007-10-25 ANOVA_TOOLS_HANDLE_AUTO_WRONG
//virtual
bool		ANOVAOneWayRM::GetAnovaToolsOption(bool bRow, int& nOption)
{
	nOption = bRow? DRTREE_ANOVA_ONE_WAY_RAW : DRTREE_ANOVA_ONE_WAY_INDEXED;
	return true;
}
///end ANOVA_TOOLS_HANDLE_AUTO_WRONG

//virtual 
string 	ANOVAOneWayRM::GetResultBookName(TreeNode& trGUI)
{
	return E_STR_ANOVA_1_WAY_RM_REPORT_TABLE_BOOK_SHORT_NAME;
}
