/*------------------------------------------------------------------------------*
 * File Name: PAParamInitHelper.h 												*
 * Creation: 																	*
 * Purpose:																		*
 * Copyright (c) Originlab Corp. 2008											*
 * All Rights Reserved															*
 *	Folger 11/26/08 QA80-11909 v8.0980 SHOULD_ALWAYS_LOAD_FDF_FILE_SETTINGS_PLUS_CENTER_VALUE_BEFORE_PARAM_INIT_IN_PA
 *  Sandy 2008-12-17 ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
 *	Folger 12/22/08 v8.0990 CACHE_FIT_FUNCTION_IN_PA_FOR_BOTH_SET_FUNCTION_AND_PARAM_INIT
 *	Folger 03/05/09 QA80-12821-P2 CANCEL_SET_FUNCTIONS_IN_PA_FITTING_CAUSE_ORIGIN_CRASH
 *	Folger 05/06/09 QA80-13544 IMPROVE_PA_SPEED_WHEN_GO_FROM_FIND_PEAK_TO_FIT_PEAK
 *	Folger 05/12/09 NANOSIZER_FITTING_BASED_SUPPORT								*
 *	Kenny 12/24/2009 QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST*
 *------------------------------------------------------------------------------*/

#ifndef		__PA_PARAMS_INIT_MANAGER_H__
#define		__PA_PARAMS_INIT_MANAGER_H__

#include "PeakParamInitHelperBase.h"

#ifndef _PA_FUNC_CATE_INFO
#define _PA_FUNC_CATE_INFO
#define STR_PA_NLSF_CAT_BASELINE		"Baseline"
#define STR_PA_NLSF_CAT_PEAK			"PFW"
#define STR_GAUSSIAN_FUNC			"Gaussian"
#define STR_PA_DEFAULT_FUNC			STR_GAUSSIAN_FUNC
#define STR_PA_DEFAULT_FDF			STR_GAUSSIAN_FUNC
#define IS_DEFAULT_PA_FUNC(_STR)	(lstrcmpi(_STR, STR_PA_DEFAULT_FUNC)==0)
#endif //_PA_FUNC_CATE_INFO

#define		STR_OFFSET_PARAM_NAME_PFM			"y0"

struct	PEAKINFOARGUMENTSLISTBASE				/// peak info arguments list base
{	
	vector			vX;
	vector			vY;
	vector			vXBL;
	vector			vYBL;
	bool			bSubtractBaseline;
	double			dAverageWidth;
	int				nSmoothPoint;
};

struct	PEAKINFOARGUMENTSLISTPARAMS				/// peak info arguments list params
{
	vector			vCenters;
	vector			vHeights;
};

struct	PEAKINFOARGUMENTSLISTBASELINE			/// peak info arguments list baseline
{
	string			strFunction;
	vector			vParamValues;
	vector<string>	vsParamNames;
};

class PAParamInitHelper : public PeakParamInitHelperBase
{
public:
	
	PAParamInitHelper(NLFitSession *pFitSession);
	~PAParamInitHelper();

	/// virtual
	bool		InitParamsMngr(PEAKINFOARGUMENTSLISTPARAMS*				pstPEAKINFOARGUMENTSLISTPARAMS = NULL,
							PEAKINFOARGUMENTSLISTFUNCTIONS*				pstPEAKINFOARGUMENTSLISTFUNCTIONS = NULL,
							PEAKINFOARGUMENTSLISTBASE*					pstPEAKINFOARGUMENTSLISTBASE = NULL,
							PEAKINFOARGUMENTSLISTBASELINE*				pstPEAKINFOARGUMENTSLISTBASELINE = NULL,
							bool*										pbHasBaselinePeak = NULL,
							bool										bLoadValuesFromFDFOnly = false,
							bool										bBaselineParamFixed = false);

	/// virtual
	bool		ReinitParamsMngrOnFuncChange(const vector<int>&			vnPeakIndecies,
									PEAKINFOARGUMENTSLISTFUNCTIONS*		pstPEAKINFOARGUMENTSLISTFUNCTIONS = NULL,
									bool								bLoadValuesFromFDFOnly= false);

	/// virtual
	bool		ReinitParamsMngrOnPeakChange(const vector<int>&			vnPeakIndecies,
									PEAKINFOARGUMENTSLISTPARAMS&		stPEAKINFOARGUMENTSLISTPARAMS,
									LPCSTR								lpcszDefaultFunction,
									bool								bLoadValuesFromFDFOnly = false,
									bool								bRemovePeak = false
									);
	
	/// virtual
	LPCSTR				GetPeakFuncCategory()		{ return STR_PA_NLSF_CAT_PEAK; }
	
	/// virtual
	LPCSTR				GetBaselineFuncCategory()	{ return STR_PA_NLSF_CAT_BASELINE; }
	
private:
	//----- Iris 11/27/2008 v8.0980 PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
	//bool		setBaselineFuncParam(const vector& vXBL, const vector& vYBL, PEAKINFOARGUMENTSLISTBASELINE& stPEAKINFOARGUMENTSLISTBASELINE, bool bLoadValuesFromFDFOnly = false);
	bool		setBaselineFuncParam(const vector& vXBL, const vector& vYBL, PEAKINFOARGUMENTSLISTBASELINE& stPEAKINFOARGUMENTSLISTBASELINE, bool bLoadValuesFromFDFOnly = false, bool bNeedResetParamSettingsFromFDF = true, bool bBaselineParamFixed = false);
	//----- 

	bool		setPeakFuncParam(int nPeakWithOffset, double dCenter, double dHeight, LPCSTR lpcszFunction, const vector& vX, const vector& vY,
								//----- Iris 11/27/2008 v8.0980 PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
								//const vector& vXBL, const vector& vYBL,	bool bSubtractBaseline, double dAverageWidth, int nSmoothPoint, bool bLoadValuesFromFDFOnly = false);
								const vector& vXBL, const vector& vYBL,	bool bSubtractBaseline, double dAverageWidth, int nSmoothPoint, bool bLoadValuesFromFDFOnly = false, bool bNeedResetParamSettingsFromFDF = true);
								//-----								

	bool		hasBaselinePeak();

	PEAKINFOARGUMENTSLISTPARAMS&	getPeakInfoParams();
	/// virtual
	void							setPeakInfoParams(const PEAKINFOARGUMENTSLISTPARAMS& stPEAKINFOARGUMENTSLISTPARAMS);
	
	PEAKINFOARGUMENTSLISTFUNCTIONS&	getPeakInfoFunctions();
	void							setPeakInfoFunctions(const PEAKINFOARGUMENTSLISTFUNCTIONS& stPEAKINFOARGUMENTSLISTFUNCTIONS);
	void							setPeakInfoFunctions(const vector<int>& vnPeakIndecies, const PEAKINFOARGUMENTSLISTFUNCTIONS* pstPEAKINFOARGUMENTSLISTFUNCTIONS = NULL);
	void							setPeakInfoOneFunction(string strFunction, int nFunc = 0);
	void							setPeakInfoFunctionsSize(int nSize);
	int								getPeakInfoFunctionsSize();
	
	PEAKINFOARGUMENTSLISTBASE&		getPeakInfoBase();
	void							setPeakInfoBase(const PEAKINFOARGUMENTSLISTBASE& stPEAKINFOARGUMENTSLISTBASE);
	
	PEAKINFOARGUMENTSLISTBASELINE&	getPeakInfoBaseline();
	void							setPeakInfoBaseline(const PEAKINFOARGUMENTSLISTBASELINE& stPEAKINFOARGUMENTSLISTBASELINE);
	
	int			getNumPeaksExcludeBaseline();

	bool		createGaussianPeakByNLSFEvaluate(const vector& vx, double dWholeWidth, double xc, double yc, vector& vParams, vector& vGaussianPeak = NULL, TreeNode &trGaussianFF = NULL);
	
	void		pfmInitGaussianParameters(vector& vParams, double xc, double yc, double dWholeWidth);
	
	bool		setPeakCenterValue(vector& vParams, const TreeNode& trFF, double rCenter);
	
	int			getPeaksOffset();
	
	bool		loadParamSettingsFromFDF(const TreeNode& trFDF, vector& vParams, vector<string>& vsParamNames = NULL);
	
	//------ Folger 11/26/08 QA80-11909 v8.0980 SHOULD_ALWAYS_LOAD_FDF_FILE_SETTINGS_PLUS_CENTER_VALUE_BEFORE_PARAM_INIT_IN_PA
	bool		isParamInitCodeEmpty(TreeNode& trFDF);
	//------

private:

	bool						m_bHasBaselinePeak;
	
	PEAKINFOARGUMENTSLISTPARAMS		m_stPEAKINFOARGUMENTSLISTPARAMS;
	PEAKINFOARGUMENTSLISTFUNCTIONS	m_stPEAKINFOARGUMENTSLISTFUNCTIONS;
	PEAKINFOARGUMENTSLISTBASE		m_stPEAKINFOARGUMENTSLISTBASE;
	PEAKINFOARGUMENTSLISTBASELINE	m_stPEAKINFOARGUMENTSLISTBASELINE;

	FitFunctionInfo				m_defaultFitFunctionInfo;
};

PAParamInitHelper::PAParamInitHelper(NLFitSession *pFitSession) : PeakParamInitHelperBase(pFitSession)
{
	m_bHasBaselinePeak = false;

	m_defaultFitFunctionInfo.strFunction = STR_GAUSSIAN_FUNC;
	string	strCategory = GetPeakFuncCategory();
	bool	bLoadFDF = nlf_get_fdf_filename(STR_GAUSSIAN_FUNC, &strCategory, NULL, &m_defaultFitFunctionInfo.strFuncFile);
	ASSERT(bLoadFDF);
	bool	bLoadFF = nlsf_load_FDF_to_tree(m_defaultFitFunctionInfo.strFuncFile, &m_defaultFitFunctionInfo.trFF, FDFT_CONVERT_BOOL_TO_01, true);
	ASSERT(bLoadFF);
}

PAParamInitHelper::~PAParamInitHelper()
{
}

bool		PAParamInitHelper::InitParamsMngr(PEAKINFOARGUMENTSLISTPARAMS*				pstPEAKINFOARGUMENTSLISTPARAMS/* = NULL*/,
											PEAKINFOARGUMENTSLISTFUNCTIONS*				pstPEAKINFOARGUMENTSLISTFUNCTIONS/* = NULL*/,
											PEAKINFOARGUMENTSLISTBASE*					pstPEAKINFOARGUMENTSLISTBASE/* = NULL*/,
											PEAKINFOARGUMENTSLISTBASELINE*				pstPEAKINFOARGUMENTSLISTBASELINE/* = NULL*/,
											bool*										pbHasBaselinePeak/* = NULL*/,
											bool										bLoadValuesFromFDFOnly/* = false*/,
											bool										bBaselineParamFixed/* = false*/)
{
	//----- Iris 11/27/2008 v8.0980 PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
	bool bNeedResetParamSettingsFromFDF = true; // true if function changed 
	if( NULL == pstPEAKINFOARGUMENTSLISTPARAMS
		&& NULL == pstPEAKINFOARGUMENTSLISTFUNCTIONS
		&& NULL == pstPEAKINFOARGUMENTSLISTBASE
		&& NULL == pstPEAKINFOARGUMENTSLISTBASELINE )
		{
			bNeedResetParamSettingsFromFDF = false; // false if click parameter init button to do init
		}
	//-----
		
	if ( pbHasBaselinePeak )
		m_bHasBaselinePeak = *pbHasBaselinePeak;
	
	if ( pstPEAKINFOARGUMENTSLISTPARAMS )
		setPeakInfoParams(*pstPEAKINFOARGUMENTSLISTPARAMS);
	
	vector<int> vnPeakIndecies;
	vnPeakIndecies.Data(0, getNumPeaksExcludeBaseline() - 1);
	setPeakInfoFunctions(vnPeakIndecies, pstPEAKINFOARGUMENTSLISTFUNCTIONS);
	
	if ( pstPEAKINFOARGUMENTSLISTBASE )
		setPeakInfoBase(*pstPEAKINFOARGUMENTSLISTBASE);
	
	if ( pstPEAKINFOARGUMENTSLISTBASELINE )
		setPeakInfoBaseline(*pstPEAKINFOARGUMENTSLISTBASELINE);
	
	/// baseline peak
	if ( hasBaselinePeak() )
	{
		//----- Iris 11/27/2008 v8.0980 PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
		//if ( !setBaselineFuncParam(getPeakInfoBase().vXBL, getPeakInfoBase().vYBL, getPeakInfoBaseline(), bLoadValuesFromFDFOnly) )
		if ( !setBaselineFuncParam(getPeakInfoBase().vXBL, getPeakInfoBase().vYBL, getPeakInfoBaseline(), bLoadValuesFromFDFOnly, bNeedResetParamSettingsFromFDF, bBaselineParamFixed) )
		//-----
			return false;
	}
	
	int		nNumPeaks = getNumPeaksExcludeBaseline();
	///------ Folger 03/05/09 QA80-12821-P2 CANCEL_SET_FUNCTIONS_IN_PA_FITTING_CAUSE_ORIGIN_CRASH
	if ( pstPEAKINFOARGUMENTSLISTFUNCTIONS && nNumPeaks >= pstPEAKINFOARGUMENTSLISTFUNCTIONS->vsFunctions.GetSize() )
		nNumPeaks = pstPEAKINFOARGUMENTSLISTFUNCTIONS->vsFunctions.GetSize();
	///------ End CANCEL_SET_FUNCTIONS_IN_PA_FITTING_CAUSE_ORIGIN_CRASH
	
	//--Sandy 2008-12-17 ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
	string strTitle = _L("Parameters Initializing......");
	string strTips;
	/// Kenny 12/24/2009 QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST
	//progressBox pb("", PBOX_TOPMOST, nNumPeaks < NLFIT_NUM_PEAKS_THRESHOLD_TO_SHOW_PROGRESSBOX? true:false);
	progressBox pb("", PBOX_DEFAULT_STYLE, nNumPeaks < NLFIT_NUM_PEAKS_THRESHOLD_TO_SHOW_PROGRESSBOX? true:false);
	/// End QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST
	pb.SetText(strTitle, PBOXT_TITLE);
	pb.SetRange(0,nNumPeaks);
	string str;
	//--end ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
	
	for ( int nPeak = 0; nPeak < nNumPeaks; ++nPeak )
	{
		
		//--Sandy 2008-12-17 ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
        strTips.Format(_L("Parameters initializing, current peak = %d......"), nPeak);
        if(pb.Set(nPeak))
        {
            pb.SetText(strTips, PBOXT_MIDCENTER);
        }
        else
        {
            out_str("User abort!");
            break;
        }
        //--endADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
        
		if ( !setPeakFuncParam(nPeak + getPeaksOffset(), getPeakInfoParams().vCenters[nPeak], getPeakInfoParams().vHeights[nPeak],
			getPeakInfoFunctions().vsFunctions[nPeak],
			getPeakInfoBase().vX,
			getPeakInfoBase().vY,
			getPeakInfoBase().vXBL,
			getPeakInfoBase().vYBL,
			getPeakInfoBase().bSubtractBaseline,
			getPeakInfoBase().dAverageWidth,
			getPeakInfoBase().nSmoothPoint,
			//----- Iris 11/27/2008 v8.0980 PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
			//bLoadValuesFromFDFOnly) )
			bLoadValuesFromFDFOnly,
			bNeedResetParamSettingsFromFDF) )
			//-----
			return false;
	}
	
	return true;
}

bool		PAParamInitHelper::ReinitParamsMngrOnFuncChange(const vector<int>&			vnPeakIndecies,
													PEAKINFOARGUMENTSLISTFUNCTIONS*		pstPEAKINFOARGUMENTSLISTFUNCTIONS/* = NULL*/,
													bool								bLoadValuesFromFDFOnly/* = false*/)
{
	/// baseline function can only be changed by edit function column,
	/// it's impossible to change baseline function and normal peak function together.
	if ( hasBaselinePeak() && vnPeakIndecies.GetSize() > 0 && vnPeakIndecies[0] == 0 )
	{
		GetNLParamsMngr()->GetFuncName(getPeakInfoBaseline().strFunction, NULL, 0);
		if ( !setBaselineFuncParam(getPeakInfoBase().vXBL, getPeakInfoBase().vYBL, getPeakInfoBaseline(), bLoadValuesFromFDFOnly) )
				return false;
		
		return true;
	}
	
	setPeakInfoFunctions(vnPeakIndecies - getPeaksOffset(), pstPEAKINFOARGUMENTSLISTFUNCTIONS);
	
	for ( int ii=0; ii<vnPeakIndecies.GetSize(); ++ii )
	{
		int nPeak = vnPeakIndecies[ii];
		int	nPeakWithoutOffset = vnPeakIndecies[ii] - getPeaksOffset();
				
		if ( !setPeakFuncParam(nPeak, getPeakInfoParams().vCenters[nPeakWithoutOffset], getPeakInfoParams().vHeights[nPeakWithoutOffset],
			getPeakInfoFunctions().vsFunctions[nPeakWithoutOffset],
			getPeakInfoBase().vX,
			getPeakInfoBase().vY,
			getPeakInfoBase().vXBL,
			getPeakInfoBase().vYBL,
			getPeakInfoBase().bSubtractBaseline,
			getPeakInfoBase().dAverageWidth,
			getPeakInfoBase().nSmoothPoint,
			bLoadValuesFromFDFOnly) )
			return false;
	}

	return true;
}

/// more need to do when add or delete peaks... Folger
bool		PAParamInitHelper::ReinitParamsMngrOnPeakChange(const vector<int>&			vnPeakIndecies,
													PEAKINFOARGUMENTSLISTPARAMS&		stPEAKINFOARGUMENTSLISTPARAMS,
													LPCSTR								lpcszDefaultFunction,
													bool								bLoadValuesFromFDFOnly/* = false*/,
													bool								bRemovePeak/* = false*/
													)
{
	vector&				vCenters = getPeakInfoParams().vCenters;
	vector&				vHeights = getPeakInfoParams().vHeights;
	vector<string>&		vsFunctions = getPeakInfoFunctions().vsFunctions;
	
	for ( int ii=0; ii<vnPeakIndecies.GetSize(); ++ii )
	{
		int nPeak = vnPeakIndecies[ii];
		
		if ( bRemovePeak )
		{
			vCenters.RemoveAt(nPeak);
			vHeights.RemoveAt(nPeak);
			vsFunctions.RemoveAt(nPeak);
			GetNLParamsMngr()->RemovePeak(nPeak + getPeaksOffset());
			continue;
		}

		vCenters.SetAtGrow(nPeak, stPEAKINFOARGUMENTSLISTPARAMS.vCenters[ii]);
		vHeights.SetAtGrow(nPeak, stPEAKINFOARGUMENTSLISTPARAMS.vHeights[ii]);
		if ( nPeak >= vsFunctions.GetSize() )
			vsFunctions.SetAtGrow(nPeak, lpcszDefaultFunction);
		
		if ( !setPeakFuncParam(nPeak + getPeaksOffset(), getPeakInfoParams().vCenters[nPeak], getPeakInfoParams().vHeights[nPeak],
			getPeakInfoFunctions().vsFunctions[nPeak],
			getPeakInfoBase().vX,
			getPeakInfoBase().vY,
			getPeakInfoBase().vXBL,
			getPeakInfoBase().vYBL,
			getPeakInfoBase().bSubtractBaseline,
			getPeakInfoBase().dAverageWidth,
			getPeakInfoBase().nSmoothPoint,
			bLoadValuesFromFDFOnly) )
			return false;
	}
	
	return true;
}

bool		PAParamInitHelper::hasBaselinePeak()
{
	return m_bHasBaselinePeak;
}

PEAKINFOARGUMENTSLISTPARAMS&	PAParamInitHelper::getPeakInfoParams()
{
	return m_stPEAKINFOARGUMENTSLISTPARAMS;
}

/// virtual
void							PAParamInitHelper::setPeakInfoParams(const PEAKINFOARGUMENTSLISTPARAMS& stPEAKINFOARGUMENTSLISTPARAMS)
{
	m_stPEAKINFOARGUMENTSLISTPARAMS = stPEAKINFOARGUMENTSLISTPARAMS;
}

PEAKINFOARGUMENTSLISTFUNCTIONS&	PAParamInitHelper::getPeakInfoFunctions()
{
	return m_stPEAKINFOARGUMENTSLISTFUNCTIONS;
}

void							PAParamInitHelper::setPeakInfoFunctionsSize(int nSize)
{
	m_stPEAKINFOARGUMENTSLISTFUNCTIONS.vsFunctions.SetSize(nSize);
}

int								PAParamInitHelper::getPeakInfoFunctionsSize()
{
	return m_stPEAKINFOARGUMENTSLISTFUNCTIONS.vsFunctions.GetSize();
}

void							PAParamInitHelper::setPeakInfoFunctions(const PEAKINFOARGUMENTSLISTFUNCTIONS& stPEAKINFOARGUMENTSLISTFUNCTIONS)
{
	m_stPEAKINFOARGUMENTSLISTFUNCTIONS = stPEAKINFOARGUMENTSLISTFUNCTIONS;
}

void							PAParamInitHelper::setPeakInfoFunctions(const vector<int>& vnPeakIndecies, const PEAKINFOARGUMENTSLISTFUNCTIONS* pstPEAKINFOARGUMENTSLISTFUNCTIONS/* = NULL*/)
{
	setPeakInfoFunctionsSize(getNumPeaksExcludeBaseline());
	
	for (int ii=0; ii<vnPeakIndecies.GetSize(); ++ii )
	{
		int nPeak = vnPeakIndecies[ii];
		if ( pstPEAKINFOARGUMENTSLISTFUNCTIONS )
		{
			ASSERT(nPeak < getNumPeaksExcludeBaseline());
			///------ Folger 03/05/09 QA80-12821-P2 CANCEL_SET_FUNCTIONS_IN_PA_FITTING_CAUSE_ORIGIN_CRASH
			if ( ii >= pstPEAKINFOARGUMENTSLISTFUNCTIONS->vsFunctions.GetSize() )
				return;
			///------ End CANCEL_SET_FUNCTIONS_IN_PA_FITTING_CAUSE_ORIGIN_CRASH
			setPeakInfoOneFunction(pstPEAKINFOARGUMENTSLISTFUNCTIONS->vsFunctions[ii], nPeak);
		}
		else
		{
			#ifdef _DEBUG
			int		nNumPeaks;
			GetNLParamsMngr()->GetNumMultiplicity(nNumPeaks);
			ASSERT(nPeak < nNumPeaks);
			#endif	///_DEBUG
			string strFunc;
			GetNLParamsMngr()->GetFuncName(strFunc, NULL, nPeak + getPeaksOffset());
			setPeakInfoOneFunction(strFunc, nPeak);
		}
	}
}

void							PAParamInitHelper::setPeakInfoOneFunction(string strFunction, int nFunc/* = 0*/)
{
	m_stPEAKINFOARGUMENTSLISTFUNCTIONS.vsFunctions[nFunc] = strFunction;
}

PEAKINFOARGUMENTSLISTBASE&		PAParamInitHelper::getPeakInfoBase()
{
	return m_stPEAKINFOARGUMENTSLISTBASE;
}

void							PAParamInitHelper::setPeakInfoBase(const PEAKINFOARGUMENTSLISTBASE& stPEAKINFOARGUMENTSLISTBASE)
{
	m_stPEAKINFOARGUMENTSLISTBASE = stPEAKINFOARGUMENTSLISTBASE;
}

PEAKINFOARGUMENTSLISTBASELINE&	PAParamInitHelper::getPeakInfoBaseline()
{
	return m_stPEAKINFOARGUMENTSLISTBASELINE;
}

void							PAParamInitHelper::setPeakInfoBaseline(const PEAKINFOARGUMENTSLISTBASELINE& stPEAKINFOARGUMENTSLISTBASELINE)
{
	m_stPEAKINFOARGUMENTSLISTBASELINE = stPEAKINFOARGUMENTSLISTBASELINE;
}

int			PAParamInitHelper::getNumPeaksExcludeBaseline()
{
	vector&	vv = getPeakInfoParams().vCenters;
	return vv.GetSize();
}

//----- Iris 11/27/2008 v8.0980 PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
//bool		PAParamInitHelper::setBaselineFuncParam(const vector& vXBL, const vector& vYBL, PEAKINFOARGUMENTSLISTBASELINE& stPEAKINFOARGUMENTSLISTBASELINE, bool bLoadValuesFromFDFOnly/* = false*/)
bool		PAParamInitHelper::setBaselineFuncParam(const vector& vXBL, const vector& vYBL, PEAKINFOARGUMENTSLISTBASELINE& stPEAKINFOARGUMENTSLISTBASELINE, bool bLoadValuesFromFDFOnly/* = false*/, bool bNeedResetParamSettingsFromFDF/* = true*/, bool bBaselineParamFixed/* = false*/)
//-----
{
	//----- Iris 11/27/2008 v8.0980 NOT_KEEP_FIX_IF_FIX_BASELINE_PARAMS_IN_BASETREAT
	if( !bBaselineParamFixed )
	//-----
	{
		string	strFuncFile;
		string	strCategory = GetBaselineFuncCategory();
		if ( !nlf_get_fdf_filename(stPEAKINFOARGUMENTSLISTBASELINE.strFunction, &strCategory, NULL, &strFuncFile) )
			return error_report("nlf_get_fdf_filename failed for " + stPEAKINFOARGUMENTSLISTBASELINE.strFunction);
	
		Tree	trFF;
		if ( !nlsf_load_FDF_to_tree(strFuncFile, &trFF, FDFT_CONVERT_BOOL_TO_01, true) )
			return error_report("get baseline FDF fails");
	
		//------ Folger 11/26/08 QA80-11909 v8.0980 SHOULD_ALWAYS_LOAD_FDF_FILE_SETTINGS_PLUS_CENTER_VALUE_BEFORE_PARAM_INIT_IN_PA
		/*
		if ( bLoadValuesFromFDFOnly )
		{
			//if ( !loadParamSettingsFromFDF(trFF, stPEAKINFOARGUMENTSLISTBASELINE.vParamValues, stPEAKINFOARGUMENTSLISTBASELINE.vsParamNames) )
				//return error_report("baseline parameter settings load fail");
			return GetFitSession()->SetParamByFDFSettings(0);
		}
		*/
		//----- Iris 11/27/2008 v8.0980 PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
		//bool	bRet = GetFitSession()->SetParamByFDFSettings(0);
		bool bRet;
		if(bNeedResetParamSettingsFromFDF)
		{
			bRet = GetFitSession()->SetParamByFDFSettings(0);
		}
		else
		{
			bRet = GetFitSession()->GetParamsInitInfo(0, stPEAKINFOARGUMENTSLISTBASELINE.vParamValues) > 0;
		}		
		//----- end PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
		if ( !bRet || bLoadValuesFromFDFOnly || isParamInitCodeEmpty(trFF) )
			return bRet;
		//------ End SHOULD_ALWAYS_LOAD_FDF_FILE_SETTINGS_PLUS_CENTER_VALUE_BEFORE_PARAM_INIT_IN_PA
		
		if ( !nlsf_init(trFF, vXBL, vYBL, stPEAKINFOARGUMENTSLISTBASELINE.vsParamNames, stPEAKINFOARGUMENTSLISTBASELINE.vParamValues) )
			return error_report("baseline parameters initialize fail");
	}
	
	for ( int nParam=0; nParam<stPEAKINFOARGUMENTSLISTBASELINE.vsParamNames.GetSize(); ++ nParam )
	{
		GetNLParamsMngr()->SetOneFuncParam(0, 0, nParam, &stPEAKINFOARGUMENTSLISTBASELINE.vParamValues[nParam]/*, NULL, NULL, stPEAKINFOARGUMENTSLISTBASELINE.vsParamNames[nParam]*/);
	}

	return true;
}

bool		PAParamInitHelper::setPeakFuncParam(int nPeakWithOffset, double dCenter, double dHeight, LPCSTR lpcszFunction, const vector& vX, const vector& vY,
												//----- Iris 11/27/2008 v8.0980 PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
												//const vector& vXBL, const vector& vYBL,	bool bSubtractBaseline, double dAverageWidth, int nSmoothPoint, bool bLoadValuesFromFDFOnly/* = false*/)
												const vector& vXBL, const vector& vYBL,	bool bSubtractBaseline, double dAverageWidth, int nSmoothPoint, bool bLoadValuesFromFDFOnly/* = false*/,
												bool bNeedResetParamSettingsFromFDF/* = true*/)
												//-----
												
{
	vector<string>	vstrParams;
	vector			vParams;

	//------ Folger 11/26/08 QA80-11909 v8.0980 SHOULD_ALWAYS_LOAD_FDF_FILE_SETTINGS_PLUS_CENTER_VALUE_BEFORE_PARAM_INIT_IN_PA
	//if ( bLoadValuesFromFDFOnly )
	//{
		///*
		//TreeNode	trFF;
		//if ( IS_DEFAULT_PA_FUNC(lpcszFunction) )
		//{
			//trFF = m_defaultFitFunctionInfo.trFF;
		//}
		//else
		//{
			//CheckUpdateCacheFitFunctionInfo(lpcszFunction);
			//trFF = m_cacheFitFunctionInfo.trFF;
		//}
			//
		//if ( !loadParamSettingsFromFDF(trFF, vParams, vstrParams) )
			//return error_report("baseline parameter settings load fail");
		//*/
		//return GetFitSession()->SetParamByFDFSettings(nPeakWithOffset);
	//}
	//----- Iris 11/27/2008 v8.0980 PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
	//bool	bRet = GetFitSession()->SetParamByFDFSettings(nPeakWithOffset);
	///------ Folger 05/06/09 QA80-13544 IMPROVE_PA_SPEED_WHEN_GO_FROM_FIND_PEAK_TO_FIT_PEAK
	//bool bRet;
	//if(bNeedResetParamSettingsFromFDF)
	//{
		//bRet = GetFitSession()->SetParamByFDFSettings(nPeakWithOffset);
	//}
	//else
	bool bRet = true;
	if ( !bNeedResetParamSettingsFromFDF )
	///------ End IMPROVE_PA_SPEED_WHEN_GO_FROM_FIND_PEAK_TO_FIT_PEAK
	{
		bRet = GetFitSession()->GetParamsInitInfo(nPeakWithOffset, vParams) > 0;
	}	
	//----- end PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
	if ( !bRet || bLoadValuesFromFDFOnly )
		return bRet;
	//------ End SHOULD_ALWAYS_LOAD_FDF_FILE_SETTINGS_PLUS_CENTER_VALUE_BEFORE_PARAM_INIT_IN_PA
	
	vector 			vyGaussian, vGaussianParams;
	
	if ( !IS_DEFAULT_PA_FUNC(lpcszFunction) )
	{
		if( !createGaussianPeakByNLSFEvaluate(vX, dAverageWidth, dCenter, dHeight, vGaussianParams, vyGaussian, m_defaultFitFunctionInfo.trFF) )
		{
			return error_report("_construct_one_peak_node fail at peak" + nPeakWithOffset);
		}
		
		CheckUpdateCacheFitFunctionInfo(lpcszFunction);
		
		//------ Folger 11/26/08 QA80-11909 v8.0980 SHOULD_ALWAYS_LOAD_FDF_FILE_SETTINGS_PLUS_CENTER_VALUE_BEFORE_PARAM_INIT_IN_PA
		if ( isParamInitCodeEmpty(GetCacheFitFunctionInfo().trFF) )
		{
			//----- Iris 11/27/2008 v8.0980 PA_IMPROVE_PARAM_INIT_IF_LOAD_PARAM_SETTINGS_FROM_FDF
			// NLFitSession::SetParamByFDFSettings directly set param value to NLParamsMngr without change vParams, so here need init vParams from NLParamsMngr if vParams is empty
			if(0 == vParams.GetSize())
			//-----
				GetNLParamsMngr()->GetParamValues(vParams, 0, nPeakWithOffset, true); 
		}
		else
		{
		///------ End SHOULD_ALWAYS_LOAD_FDF_FILE_SETTINGS_PLUS_CENTER_VALUE_BEFORE_PARAM_INIT_IN_PA
			if(!nlsf_init(GetCacheFitFunctionInfo().trFF, vX, vyGaussian, vstrParams, vParams))
			{
				return error_report("_construct_one_peak_node fail at peak" + nPeakWithOffset);
			}
		}	//------ Folger 11/26/08 QA80-11909 v8.0980 SHOULD_ALWAYS_LOAD_FDF_FILE_SETTINGS_PLUS_CENTER_VALUE_BEFORE_PARAM_INIT_IN_PA
		
		setPeakCenterValue(vParams, GetCacheFitFunctionInfo().trFF, dCenter);
		if(vParams.GetSize() > 0 && vstrParams.GetSize() > 0 && 0 == lstrcmpi(vstrParams[0], STR_OFFSET_PARAM_NAME_PFM) )
			vParams[0] = 0;
	}
	else
	{
	
		pfmInitGaussianParameters(vGaussianParams, dCenter, dHeight, dAverageWidth);
		vector<string> vstrGuassianParams = {"y0", "xc", "A", "w"};	
		vstrParams = vstrGuassianParams;
		vParams = vGaussianParams;
	}

	int		nParamOffset = GetNLParamsMngr()->GetFunctionParameterOffset(nPeakWithOffset);
	for ( int nParam=nParamOffset; nParam<vParams.GetSize(); ++ nParam )
	{
		GetNLParamsMngr()->SetOneFuncParam(nPeakWithOffset, 0, nParam - nParamOffset, &vParams[nParam]/*, NULL, NULL, vstrParams[nParam]*/);
	}

	return bRet;
}

bool		PAParamInitHelper::createGaussianPeakByNLSFEvaluate(const vector& vx, double dWholeWidth, double xc, double yc, vector& vParams, vector& vGaussianPeak/* = NULL*/, TreeNode &trGaussianFF/* = NULL*/)
{
	pfmInitGaussianParameters(vParams, xc, yc, dWholeWidth);

	if ( vGaussianPeak == NULL )
		return true;

	if ( trGaussianFF )
		return nlsf_evaluate(trGaussianFF, vx, vGaussianPeak, vParams);

	return nlsf_evaluate(STR_PA_DEFAULT_FUNC, GetPeakFuncCategory(), vx, vGaussianPeak, vParams);
}
	
void		PAParamInitHelper::pfmInitGaussianParameters(vector& vParams, double xc, double yc, double dWholeWidth)
{
	static const double l_dSqrt = NLFIT_AREA_PARAMETER_CALCULATION_FACTOR;
	
	vParams.SetSize(4);
	vParams[0] = 0;
	vParams[1] = xc;
	vParams[3] = dWholeWidth;
	vParams[2] = yc*vParams[3] * l_dSqrt;
}

int			PAParamInitHelper::getPeaksOffset()
{
	return hasBaselinePeak() ? 1 : 0;
}

bool		PAParamInitHelper::setPeakCenterValue(vector& vParams, const TreeNode& trFF, double rCenter)
{
	TreeNode	trPeakCenter = tree_get_node_by_tagname(trFF, "PeakCenter", true);
	
	if ( !trPeakCenter || trPeakCenter.nVal > vParams.GetSize() )
	{
		ASSERT(false);
		return false;
	}
	
	vParams[trPeakCenter.nVal - 1] = rCenter;
	return true;
}

bool		PAParamInitHelper::loadParamSettingsFromFDF(const TreeNode& trFDF, vector& vParams, vector<string>& vsParamNames/* = NULL*/)
{
	vector<string>		vsNames;
	int					nNumParamInFDF = nlsf_get_fit_param_names(trFDF, vsNames);
	
	if ( vsParamNames )
		vsParamNames = vsNames;
	
	TreeNode	trValues = tree_get_node_by_tagname(trFDF, STR_FDF_SETTING_INIT_VAL, true);
	
	return nlf_set_param_values_vector(trValues ? trValues.strVal : "", vParams, nNumParamInFDF);
}

//------ Folger 11/26/08 QA80-11909 v8.0980 SHOULD_ALWAYS_LOAD_FDF_FILE_SETTINGS_PLUS_CENTER_VALUE_BEFORE_PARAM_INIT_IN_PA
bool		PAParamInitHelper::isParamInitCodeEmpty(TreeNode& trFDF)
{
	string strInitCode;
	nlsf_get_param_init_code(trFDF, strInitCode);
	return strInitCode.IsEmpty();
}
//------ End SHOULD_ALWAYS_LOAD_FDF_FILE_SETTINGS_PLUS_CENTER_VALUE_BEFORE_PARAM_INIT_IN_PA

#endif		//__PA_PARAMS_INIT_MANAGER_H__
