/*------------------------------------------------------------------------------*
 * File Name: FFWParamPage.h			 										*
 * Creation: 																	*
 * Purpose: 																	*
 * Copyright (c) Originlab Corp.	2005, 2006, 2007, 2008, 2009, 2010			*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	Jasmine 07/02/10 ORG-432-S10 DEFINE_DERIVED_PARAM_IN_PARAM_PAGE				*
 *	Folger 07/05/10 ORG-478-S1 ERROR_CHECKING_FOR_EXPRESSION_MULTIPLE_DEPENDENTS*
 *------------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------*
 this file contains one class:
 	1. FFWParamPage
 *------------------------------------------------------------------------------*/ 
 
#ifndef _FFW_PARAM_PAGE_H
#define _FFW_PARAM_PAGE_H

/*------------------------------------------------------------------------------*
 * FFWParamPage 			 													*
 *------------------------------------------------------------------------------*/

#define		STR_ITEM_SEPARATOR		','

class FFWParamPage : public FFWPageBase
{	
public:
	FFWParamPage(int nID = 0) : FFWPageBase(nID){}
	
	// Event handlers for this page
	EVENTS_BEGIN
		PAGE_ON_INIT(OnInitPage)
		PAGE_ON_ACTIVE(OnActivatePage)
		PAGE_ON_KILLACTIVE(OnKillActiviePage)
		PAGE_ON_NEXT(OnNext)
		PAGE_ON_BACK(OnBack)
		
		ON_EN_KILLFOCUS(IDC_FIT_FUNC_INDEPEND_VAR, OnIndepKillFocus)
		ON_EN_KILLFOCUS(IDC_FIT_FUNC_DEPEND_VAR, OnDepKillFocus)
		ON_EN_KILLFOCUS(IDC_FIT_FUNC_PARAM_TEXT, OnParamKillFocus)
		ON_EN_KILLFOCUS(IDC_FIT_FUNC_DERIVED_PARAM_TEXT, OnDerivedParamKillFocus)	///Jasmine 07/02/10 ORG-432-S10 DEFINE_DERIVED_PARAM_IN_PARAM_PAGE
		ON_EN_KILLFOCUS(IDC_FIT_FUNC_CONSTANT_TEXT, OnConstKillFocus)
		
		ON_BN_CLICKED(IDC_FIT_PEAK_FUNC_CHECK, OnCheckPeak)
	EVENTS_END
	
	//virtual
	BOOL OnInitPage();
	BOOL OnActivatePage();
	BOOL OnNext();
	
	BOOL OnIndepKillFocus(Control ctrl);
	BOOL OnDepKillFocus(Control ctrl);
	BOOL OnParamKillFocus(Control ctrl);
	BOOL OnDerivedParamKillFocus(Control ctrl);///Jasmine 07/02/10 ORG-432-S10 DEFINE_DERIVED_PARAM_IN_PARAM_PAGE
	BOOL OnConstKillFocus(Control ctrl);
	
	BOOL 	OnCheckPeak(Control ctrl);
	
	string 	GetName(){return "FFWParamPage";}
	
protected:
	//virtual 
	bool 	UpdateTreeToPageGUI(const TreeNode& trFunction);
	//virtual 
	bool 	UpdatePageGUIToTree(TreeNode& trFunction);
	//virtual 
	string	GetPageHintsName(bool bNextPage = false);///Jasmine 06/25/10 ORG390-P5 MOVE_FFW_HINTS_TO_TXT

private:
	bool	checkEditControlValue(Control ctrl, LPCSTR lpczCtrlName, bool bAllowEmpty, string& strErrMsg);
	bool	checkPeakFunctionParams(string& strErrMsg);	///Sophy 7/5/2010 ORG-432-S11 CHECK_PARAMS_WHEN_DEF_PEAK_FUNCTION
	/// Bill 07/05/2010 ORG-478-S1 CHECK_MULTIPLE_DEPS_IN_EXPRESSION
	bool	checkMultipleDeps(string & strErrMsg);
	///End CHECK_MULTIPLE_DEPS_IN_EXPRESSION
private:
	Button				m_checkPeak;
	
};
	
BOOL FFWParamPage::OnInitPage()
{
	_SHOW_TIME(GetPageID(), "OnInitPage")
	
	m_checkPeak = GetItem(IDC_FIT_PEAK_FUNC_CHECK);
	if ( !m_checkPeak )
		return FALSE;

	return FFWPageBase::OnInitPage();
}

BOOL FFWParamPage::OnActivatePage()
{
	_SHOW_TIME(GetPageID(), "OnActivatePage")
	
	FFWPageBase::OnActivatePage();
	OnCheckPeak(m_checkPeak);
	return TRUE;
}

BOOL FFWParamPage::OnCheckPeak(Control ctrl)
{
	string strHint = GetPageHints();
	
	if(m_checkPeak.Check)
	{
		string strPeakHint;
		///Jasmine 06/25/10 ORG390-P5 MOVE_FFW_HINTS_TO_TXT
		string strPath;	
		okutil_find_sys_path_with_file(&strPath, STR_FFW_HINTS_TXT, GLOBAL_LOCALIZED_PATH, TRUE);
		
		string strHints;
		okutil_read_file_section(strPath + STR_FFW_HINTS_TXT, "Peak Function", &strPeakHint, NULL); 
		///End MOVE_FFW_HINTS_TO_TXT
		strHint += "\r\n\r\n" + strPeakHint;
	}
	
	SetHints(strHint);
	return TRUE;
}

BOOL FFWParamPage::OnNext()
{
	Control ctrlIndep = GetItem(IDC_FIT_FUNC_INDEPEND_VAR);
	if( !OnIndepKillFocus(ctrlIndep) )
		return FALSE;	
		
	Control ctrlDep = GetItem(IDC_FIT_FUNC_DEPEND_VAR);
	if( !OnDepKillFocus(ctrlDep) )
		return FALSE;
	
	Control ctrlParam = GetItem(IDC_FIT_FUNC_PARAM_TEXT);
	if( !OnParamKillFocus(ctrlParam) )
		return FALSE;
	
	///Jasmine 07/02/10 ORG-432-S10 DEFINE_DERIVED_PARAM_IN_PARAM_PAGE
	Control ctrlDerived = GetItem(IDC_FIT_FUNC_DERIVED_PARAM_TEXT);
	if( !OnDerivedParamKillFocus(ctrlDerived) )
		return FALSE;
	///End DEFINE_DERIVED_PARAM_IN_PARAM_PAGE
	
	Control ctrlConst = GetItem(IDC_FIT_FUNC_CONSTANT_TEXT);
	if( !OnConstKillFocus(ctrlConst) )
		return FALSE;
	///Sophy 7/5/2010 ORG-432-S11 CHECK_PARAMS_WHEN_DEF_PEAK_FUNCTION
	string strErrMsg;
	if ( !checkPeakFunctionParams(strErrMsg) )
	{
		MessageBox(strErrMsg, STR_ERROR, MB_OK);
		return FALSE;
	}
	///end CHECK_PARAMS_WHEN_DEF_PEAK_FUNCTION
	return FFWPageBase::OnNext();
}

#define CHECK_EIDT_CONTROL_VALUE(_NAME, _ALLOWEMPTY)		\
	string strErrMsg;										\	
	if(	!checkEditControlValue(ctrl, _NAME, _ALLOWEMPTY, strErrMsg) )\
	{														\
		if( !strErrMsg.IsEmpty() )							\
			MessageBox(strErrMsg, STR_ERROR, MB_OK);\
		return FALSE;										\
	}														\
	return TRUE;
	
BOOL FFWParamPage::OnIndepKillFocus(Control ctrl)
{
	CHECK_EIDT_CONTROL_VALUE(_L("Independent Variables"), false)
}
BOOL FFWParamPage::OnDepKillFocus(Control ctrl)
{
	/// Bill 07/05/2010 ORG-478-S1 CHECK_MULTIPLE_DEPS_IN_EXPRESSION
	//CHECK_EIDT_CONTROL_VALUE(_L("Dependent Variables"), false)
	string strErrMsg;

	if ( !checkEditControlValue(ctrl, _L("Dependent Variables"), false, strErrMsg) ||
		 !checkMultipleDeps(strErrMsg) )
	{
		if ( !strErrMsg.IsEmpty() )
			MessageBox(strErrMsg, STR_ERROR, MB_OK);
		return FALSE;
	}
	return TRUE;
	/// End CHECK_MULTIPLE_DEPS_IN_EXPRESSION

	return TRUE;
}
BOOL FFWParamPage::OnParamKillFocus(Control ctrl)
{
	CHECK_EIDT_CONTROL_VALUE(_L("Parameters"), false)
}
///Jasmine 07/02/10 ORG-432-S10 DEFINE_DERIVED_PARAM_IN_PARAM_PAGE
BOOL FFWParamPage::OnDerivedParamKillFocus(Control ctrl)
{
	CHECK_EIDT_CONTROL_VALUE(_L("Derived Parameters"), true)
}
///End DEFINE_DERIVED_PARAM_IN_PARAM_PAGE
BOOL FFWParamPage::OnConstKillFocus(Control ctrl)
{
	CHECK_EIDT_CONTROL_VALUE(_L("Constants"), true)
}
	
bool FFWParamPage::UpdateTreeToPageGUI(const TreeNode& trFunction)
{
	//Indep&Dep
	GetItem(IDC_FIT_FUNC_INDEPEND_VAR).Text = FuncOrganizer().GetIndependVars(trFunction, STR_ITEM_SEPARATOR);
	GetItem(IDC_FIT_FUNC_DEPEND_VAR).Text = FuncOrganizer().GetDependVars(trFunction, STR_ITEM_SEPARATOR);
	
	//parameter
	GetItem(IDC_FIT_FUNC_PARAM_TEXT).Text = FuncOrganizer().GetFittingPara(trFunction);

	///Jasmine 07/02/10 ORG-432-S10 DEFINE_DERIVED_PARAM_IN_PARAM_PAGE
	//derived parameter
	GetItem(IDC_FIT_FUNC_DERIVED_PARAM_TEXT).Text = FuncOrganizer().GetDerivedParameterNames(trFunction);
	///End DEFINE_DERIVED_PARAM_IN_PARAM_PAGE
	
	//constant
	vector<string> vsVariables, vsValues;
	FuncOrganizer().GetConstants(trFunction, vsVariables, vsValues);
	
	string strConstant;
	strConstant.SetTokens(vsVariables, STR_ITEM_SEPARATOR);	
	GetItem(IDC_FIT_FUNC_CONSTANT_TEXT).Text = strConstant;
	
	//peak function
	///Sophy 7/27/2010 ORG-591-P3 PEAKFUNCTION_CHECKBOX_STATE_NOT_KEEP_FROM_FO_TO_FFW_WHEN_NOT_VALID_PEAKFUNCTION		
	//m_checkPeak.Check = FuncOrganizer().IsPeak(trFunction);	
	int nPeakFunctionCheck = 0;
	trFunction.GetAttribute(STR_PEAK_CHECK_ATTRIB, nPeakFunctionCheck);
	m_checkPeak.Check = FuncOrganizer().IsPeak(trFunction) || nPeakFunctionCheck == 1;	
	trFunction.RemoveAttribute(STR_PEAK_CHECK_ATTRIB); //only need the attribute for the first time
	///end PEAKFUNCTION_CHECKBOX_STATE_NOT_KEEP_FROM_FO_TO_FFW_WHEN_NOT_VALID_PEAKFUNCTION		

	return true;
}

bool FFWParamPage::UpdatePageGUIToTree(TreeNode& trFunction)
{
	//Indep&Dep
	vector<string> vsIndependVars;
	string strIndependVars = GetItem(IDC_FIT_FUNC_INDEPEND_VAR).Text;
	strIndependVars.GetTokens(vsIndependVars, STR_ITEM_SEPARATOR);
	FuncOrganizer().SetIndependVars(vsIndependVars, trFunction);

	vector<string> vsDependVars;
	string strDependVars = GetItem(IDC_FIT_FUNC_DEPEND_VAR).Text;
	strDependVars.GetTokens(vsDependVars, STR_ITEM_SEPARATOR);
	FuncOrganizer().SetDependVars(vsDependVars, trFunction);

	//parameter
	FuncOrganizer().SetFittingPara(GetItem(IDC_FIT_FUNC_PARAM_TEXT).Text, trFunction);
	
	///Jasmine 07/02/10 ORG-432-S10 DEFINE_DERIVED_PARAM_IN_PARAM_PAGE
	//derived parameter
	vector<string> vsNames;
	okutil_get_tokens(GetItem(IDC_FIT_FUNC_DERIVED_PARAM_TEXT).Text, &vsNames, STR_ITEM_SEPARATOR, NULL);
	FuncOrganizer().SetDerivedParameterSetting(trFunction, vsNames);
	///End DEFINE_DERIVED_PARAM_IN_PARAM_PAGE
	
	//constant
	string strConstant = GetItem(IDC_FIT_FUNC_CONSTANT_TEXT).Text;
	
	vector<string> vsVariables;
	vector<string> vsValues;
	///Sophy 7/8/2010 ORG-518-P1 PROPER_RESET_CONSTANT_SETTINGS_ON_BACK_AND_FORTH
	//int nCount = strConstant.GetTokens(vsVariables, STR_ITEM_SEPARATOR);
	//FuncOrganizer().SetConstants(vsVariables, vsValues, trFunction);
	int nExist = FuncOrganizer().GetConstants(m_pHolder->m_trFunction, vsVariables, vsValues);
	vector<string> vsNewVars;
	vector<string> vsNewVals;
	int nCount = strConstant.GetTokens(vsNewVars, STR_ITEM_SEPARATOR);
	vsNewVals.SetSize(nCount);
	for ( int iVar = 0; iVar < nExist; iVar++ )
	{
		int iIndex = vsNewVars.Find(vsVariables[iVar]);
		if ( iIndex >= 0 )
			vsNewVals[iIndex] = vsValues[iVar];
	}
	FuncOrganizer().SetConstants(vsNewVars, vsNewVals, trFunction);
	///end PROPER_RESET_CONSTANT_SETTINGS_ON_BACK_AND_FORTH

	//peak function
	FuncOrganizer().SetPeak(m_checkPeak.Check, trFunction);
	
	return true;
}

///Jasmine 06/25/10 ORG390-P5 MOVE_FFW_HINTS_TO_TXT
//virtual 
string FFWParamPage::GetPageHintsName(bool bNextPage/* = false*/)
{
	if ( !bNextPage )
		return "Variables and Parameters";
	else
		return "Variables and Parameters next page";
}
///End MOVE_FFW_HINTS_TO_TXT

//refer to NumFunctionOrganizerEx::correctVarNameList
bool FFWParamPage::checkEditControlValue(Control ctrl, LPCSTR lpczCtrlName, bool bAllowEmpty, string& strErrMsg)
{
	if(!ctrl)
		return false;
	
	string strTemp = ctrl.Text;
	strTemp.TrimLeft();
	strTemp.TrimRight();
	
	//is it empty?
	if( strTemp.IsEmpty() )
	{
		if(!bAllowEmpty)
		{
			//strErrMsg.Format("%s cannot be empty.", lpczCtrlName);
			ocu_load_msg_str(FFWERR_ST_CANNOT_BE_EMPTY, &strErrMsg, lpczCtrlName);
			return false;
		}
		return true;
	}
	
	//is it valid?
	vector<string> vsItem;
	int nCount = strTemp.GetTokens(vsItem, STR_ITEM_SEPARATOR);
	for(int ii = 0; ii < nCount; ii++)
	{
		string strName = vsItem[ii];
		strName.MakeValidCName();
		vsItem[ii] = strName;
	}

	remove_repeat_item(vsItem);
	
	strTemp.SetTokens(vsItem, STR_ITEM_SEPARATOR);
	
	if( strTemp.IsEmpty() )
	{
		strErrMsg.Format("%s are invalid.", lpczCtrlName);
		return false;
	}
	
	if(lstrcmpi(ctrl.Text, strTemp) != 0)
		ctrl.Text = strTemp;
	return true;
}

///Sophy 7/5/2010 ORG-432-S11 CHECK_PARAMS_WHEN_DEF_PEAK_FUNCTION
bool FFWParamPage::checkPeakFunctionParams(string& strErrMsg)
{
#define	MIN_PEAK_FUNCTION_PARAMS	4
	Control ctrlParam = GetItem(IDC_FIT_FUNC_PARAM_TEXT);
	string strParams = ctrlParam.Text;
	vector<string> vsParamNames;
	strParams.GetTokens(vsParamNames, STR_ITEM_SEPARATOR);
	if ( m_checkPeak.Check )
	{
		string strFirstParam = vsParamNames.GetSize() > 0 ? vsParamNames[0] : "";
		if ( vsParamNames.GetSize() < MIN_PEAK_FUNCTION_PARAMS || strFirstParam.CompareNoCase("y0") != 0 && strFirstParam.CompareNoCase("z0") != 0 )
		{
			ocu_load_err_msg_str(FO_PEAK_FUNC_MSG, &strErrMsg);
			
			strErrMsg += "\r\n\r\n" + _L("The Peak Attributes can be set on the next page.");///Jasmine 07/14/10 ORG-540-P3
			return false;
		}
	}
	return true;
}
/// End CHECK_PARAMS_WHEN_DEF_PEAK_FUNCTION

/// Bill 07/05/2010 ORG-478-S1 CHECK_MULTIPLE_DEPS_IN_EXPRESSION
bool FFWParamPage::checkMultipleDeps(string & strErrMsg)
{
	///------ Folger 07/05/10 ORG-478-S1 ERROR_CHECKING_FOR_EXPRESSION_MULTIPLE_DEPENDENTS
	//string strForm = FuncOrganizer().GetForm(m_pHolder->m_trFunction);
//
	//if ( strForm.CompareNoCase(STR_FUNCTION_FORM_EXPRESSION) == 0 &&
		 //nlf_get_dependent_variables(m_pHolder->m_trFunction) == 1 )
	//{
		//strErrMsg.Format(_L("Expression can't has multiple depend variable"));
		//return false;
	//}
	if ( !FuncOrganizer().IsAllowMultipleDeps(m_pHolder->m_trFunction) )
	{
		string	str = GetItem(IDC_FIT_FUNC_DEPEND_VAR).Text;
		if ( str.GetNumTokens(STR_ITEM_SEPARATOR) != 1 )
		{
			strErrMsg.Format(_L("Expression cannot have multiple dependent variables"));
			return false;
		}
	}
	///------ End ERROR_CHECKING_FOR_EXPRESSION_MULTIPLE_DEPENDENTS
	return true;
}
/// End CHECK_MULTIPLE_DEPS_IN_EXPRESSION
/*------------------------------------------------------------------------------*
 * FFWParamPage End		 														*
 *------------------------------------------------------------------------------*/


#endif//_FFW_PARAM_PAGE_H
