#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	method_specify,
	method_range,
	method_snd,
	method_max,
	method_min,
	method_mean,
	method_median,
	method_sd,
	method_norm,
	method_mode,
	method_sum,
	method_ref,
	method_pt,
};
enum{
	to_min,
	to_max,
	to_mean,
	to_median,
	to_sum,
};

#include <GetNBox.h> 
#include <XFBase.h>
#include <o8dlg.h>
#include <event_utils.h>

/***************************************************************************************
/// Modification Log :
/// Folger 07/23/08 BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS
/// Folger 09/25/08 QA80-12276 SET_SAMPLING_INTERVAL_FOR_YXRANGE_OUTPUT
/// Max 11/25/08 QA70-12615 v8.0975d SHARE_SAME_FUNC_FOR_NORMALIZE_AND_VNORMALIZE
/// Hong 06/07/09 QA-13673 ADD_NEW_METHOD_SUM
/// Iris 8/07/2009 QA80-13673  ADD_PICK_BUTTON_EVENTS
/// Iris 8/07/2009 QA80-13673-S1 ADD_TOTAL_DATA_INFO_GUI_TREE
/// Iris 8/13/2009 QA80-13673-P8 ADD_COMMENTS_IN_RESULT_COL
/// Sophy 8/17/2009 QA80-14087-P2 SHOW_USEFUL_MSG_ON_GET_PTS_DIALOG
/// Sophy 8/17/2009 QA80-14087-P3 NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
/// Sophy 8/17/2009 QA80-14087-P4 READ_ONLY_NODE_WITH_BETTER_DISPLAY
/// Sophy 8/18/2009 QA80-14087-P5 CURVE_NORMALIZE_GET_WRONG_RESULT_WHEN_REFER_TO_COLUMN
/// Sophy 8/18/2009 QA80-13673-P9 CNORMALIZE_FAIL_TO_SELECT_REFER_POINT_WHEN_CHANGE_PARAMETER
/// Kyle 08/19/2009 QA80-14023 FIX_OUTPUT_SAMPLING_INTERVAL_IS_LOST_WHEN_INPUT_IS_LOOSE_DATASET
/// Sophy 8/20/2009 QA80-14087-P9 MORE_CHECH_ON_USER_SETTINGS_BEFORE_EXECUTE
/// Sophy 8/31/2009 FIX_NORMALIZE_WITH_MINUS_VALUE_GET_INCORRECT_RESULT
/// Sophy 8/31/2009 QA80-14087-S1 PLOT_RESULT_CURVES_ON_SOURCE_GRAPH
/// Iris 9/01/2009 QA80-13673-P4 FIX_REF_PLOT_EFFECT_AU_EVEN_IT_IS_HIDDEN
/// Sophy 9/2/2009 IMPROVE_COMMENTS_FOR_NORMALIZE_RESULT_COLUMNS
/// Iris 9/03/2009 QA80-13673-P13 DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
/// Sophy 9/10/2009 QA80-14087-P15 CNORMALIZE_GET_DATA_FROM_PLOT_SHOULD_GET_MISSING_VALUES
/// Sophy 9/15/2009 IMPROVE_COMMENTS_FOR_NORMALIZE_RESULT_COLUMNS
/// Iris 9/18/2009 SUPORT_PICK_POINT_METHOD_FOR_SCRIPT_MODE
/// Kyle 09/22/2009 QA80-14023 FIX_SAMPLING_IS_NOT_RESET_IF_SET_INPUT_AS_OUTPUT
/// YuI 09/30/09 QA70-14399 UNNECESARY_AUTOUPDATE_IN_CASE_OF_INPUT_NEW
/// Sophy 10/12/2009 QA80-14087-P12 UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
/// Sophy 10/22/2009 QA80-14087-S4 PLOT_EACH_RESULT_ON_SOURCE_GRAPHLAYER_AS_INPUT
/// Sophy 10/22/2009 QA80-14087-P19 FORCE_NOT_REMEMBER_REF_POINT_SETTINGS_WHEN_METHOD_NOT_REF_TO_POINT
/// Folger 11/05/09 QA81-14087-P24 FAILS_TO_CREATE_OP_WHEN_PICK_REF_POINT_WITH_EVEN_SAMPLING_INPUT
/// Folger 08/02/10 ORG-672 INTEG1_SUPPORT_MULTIPLE_XYRANGES
***************************************************************************************/

//put additional include files here
//#define Y_INDEX_IN_XYRANGE 1

//#define STR_NODE_OPTION "method"	// Max 11/20/08 no need to define if use in one place only
//#define STR_VNORMALIZE_NAME "vnormalize"	// Max 11/20/08 no need to define if use in one place only

#define _NORMALIZE_METHOD_ERROR 0   //temp solution

/// Iris 9/01/2009 QA80-13673-P4 FIX_REF_PLOT_EFFECT_AU_EVEN_IT_IS_HIDDEN
#define STR_REF_PLOT_OLD_VAL			"RefPlot"
///end FIX_REF_PLOT_EFFECT_AU_EVEN_IT_IS_HIDDEN

//put your own support static functions here

///Cheney 2007-6-7 ADD_AN_ERR_CHECK_FUNC
static int _check_err_condition(TreeNode& trGetN)
{
	int nErr = CER_NO_ERROR;
	
	if(get_input_xyrange_num(trGetN.iy) <= 0 ) 
		nErr = CER_NOT_ONE_XYRANGE;
	
	if(nErr == CER_NO_ERROR && method_specify == trGetN.method.nVal && trGetN.val.dVal == 0) //if(nErr == CER_NO_ERROR && trGetN.value.dVal == 0)
		nErr = XFERR_DIVIDED_BY_ZERO;
	
	if(nErr == CER_NO_ERROR && method_pt == trGetN.method.nVal && (trGetN.picky.IsEmpty() || is_empty_or_unassigned(trGetN.picky.strVal)) )
		nErr = XFERR_PICKED_Y_CANNOT_BE_EMPTY;
	
	///Sophy 8/17/2009 QA80-14087-P3 NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
	if ( nErr == CER_NO_ERROR && method_pt == trGetN.method.nVal && trGetN.picky.dVal == 0 )
		nErr = XFERR_DIVIDED_BY_ZERO;
	///end NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
	
	///Sophy 8/20/2009 QA80-14087-P9 MORE_CHECH_ON_USER_SETTINGS_BEFORE_EXECUTE
	if ( nErr == CER_NO_ERROR && method_ref == trGetN.method.nVal )
	{
		XYRange drRef;
		drRef.Create();
		drRef.SetTree(trGetN.ref);
		
		vector vY, vX;
		if ( !drRef || !drRef.GetData(vY, vX) )
			nErr = XFERR_NO_REF_PLOT;
	}
	
	if ( nErr == CER_NO_ERROR && trGetN.oy.Range1.X.IsEmpty() && trGetN.oy.Range1.Y.IsEmpty() )
		nErr = CER_INVALID_OUT_RANGE;
	///end MORE_CHECH_ON_USER_SETTINGS_BEFORE_EXECUTE
	return nErr;
}
///end ADD_AN_ERR_CHECK_FUNC

/// Iris 9/01/2009 QA80-13673-P4 FIX_REF_PLOT_EFFECT_AU_EVEN_IT_IS_HIDDEN
static void _check_reset_ref_plot(TreeNode& trRange, int nCurrentMethod, int nCheckMethod, LPCSTR lpcszOldValAttribte)
{
	if( nCurrentMethod == nCheckMethod )
	{
		string str;
		if( trRange.GetAttribute(lpcszOldValAttribte, str) )
		{
			trRange.SetAttribute(STR_DATA_ATTRIB, str);
		}
		else
		{
			trRange.SetAttribute(STR_DATA_ATTRIB, "");
		}
	}
	else
	{
		trRange.SetAttribute(STR_DATA_ATTRIB, STR_OPTIONAL);
	}
	okutil_getn_update_ranges(&trRange);
}
///end FIX_REF_PLOT_EFFECT_AU_EVEN_IT_IS_HIDDEN

///Sophy 10/12/2009 QA80-14087-P12 UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
static bool _update_ref_point_from_range(LPCSTR lpcszRefPtsRng, double& dRefX, double& dRefY)
{
	XYRange dr;
	dr.Create(lpcszRefPtsRng, XVT_XYDATARANGE);
	if ( !dr || !dr.IsValid() )
		return false;
	
	vector vX, vY;
	if ( !dr.GetData(vY, vX, NULL, 0, DRR_GET_MISSING | DRR_BAD_WEIGHT_TREATMENT) )
		return false;
	
	dRefX = vX[0];
	dRefY = vY[0];
	return true;
}
///end UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
///--- Hong, for temp
/// Iris 8/07/2009 QA80-13673  ADD_PICK_BUTTON_EVENTS
//static int _normalize_data(vector& vv, int nMethod, double dVal)
///Sophy 8/17/2009 QA80-14087-P3 NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
//static int _normalize_data(vector& vv, int nMethod, double dVal, double dPickY)
/// Iris 9/03/2009 QA80-13673-P13 DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
//static int _normalize_data(vector& vv, int nMethod, double dVal, double dPickY, int nPtsIndex)
static int _normalize_data(vector& vv, int nMethod, double dVal, const vector& vSrcX, double dPickX, double dPickY)
///end DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
///end NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
///end ADD_PICK_BUTTON_EVENTS
{
	if ( 0 == vv.GetSize() )
		return 0;
	
	double 			dSub = 0.0, dFactor = 1.0;
	/// Iris 8/07/2009 QA80-13673  ADD_PICK_BUTTON_EVENTS
	//if ( !_get_normalize_val(dVal, dSub, vv, nMethod) )
	///Sophy 8/17/2009 QA80-14087-P3 NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
	//if ( !_get_normalize_val(dVal, dSub, vv, nMethod, &dPickY) )
	/// Iris 9/03/2009 QA80-13673-P13 DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
	//if ( !_get_normalize_val(dVal, dSub, vv, nMethod, &dPickY, &nPtsIndex) )
	if ( !_get_normalize_val(dVal, dSub, vv, nMethod, vSrcX, &dPickX, &dPickY) )
	///end DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
	///end NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
	///end ADD_PICK_BUTTON_EVENTS
		return _NORMALIZE_METHOD_ERROR;
	
	dFactor = (is_equal(0.0, dVal)) ? NANUM : 1.0 / dVal;	
	vv -= dSub;
	vv *= dFactor;
	
	return 0;
}

/// Iris 8/07/2009 QA80-13673  ADD_PICK_BUTTON_EVENTS
//static bool _get_normalize_val(double& dNormalizeVal, double& dSub, const vector& vv, int nMethod)
///Sophy 8/17/2009 QA80-14087-P3 NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
//static bool _get_normalize_val(double& dNormalizeVal, double& dSub, const vector& vv, int nMethod, double* pdPickY = NULL)
/// Iris 9/03/2009 QA80-13673-P13 DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
//static bool _get_normalize_val(double& dNormalizeVal, double& dSub, const vector& vv, int nMethod, double* pdPickY = NULL, int* pPtsIndex = NULL)
static bool _get_normalize_val(double& dNormalizeVal, double& dSub, const vector& vv, int nMethod, const vector& vSrcX = NULL, double* pdPickX = NULL, double* pdPickY = NULL)
///end DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
///end NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
///end ADD_PICK_BUTTON_EVENTS
{
	int 			nRet = STATS_NO_ERROR;
	double 			dFactor = 1.0;
	switch ( nMethod )
	{
	case method_specify:
		break;
	case method_range:
		double 		dMin, dMax;
		vv.GetMinMax(dMin, dMax);
		dSub = dMin;
		dNormalizeVal = dMax - dMin;
		break;
	case method_snd:
		nRet = ocmath_basic_summary_stats(vv.GetSize(), vv, NULL, &dSub, &dNormalizeVal);
		break;
	case method_max:
		double 		dMin, dMax;
		vv.GetMinMax(dMin, dMax);
		dNormalizeVal = dMax;
		break;
	case method_min:
		double 		dMin, dMax;
		vv.GetMinMax(dMin, dMax);
		dNormalizeVal = dMin;		
		break;
	case method_mean:
		nRet = ocmath_basic_summary_stats(vv.GetSize(), vv, NULL, &dNormalizeVal);
		break;
	case method_median:
		int 		nSize = vv.GetSize();
		vector 		vSort;
		vSort = vv;
		vSort.Sort();
		dNormalizeVal = (vSort.GetSize() == 1) ? vSort[0] : ((nSize%2) ? vSort[nSize/2] : 0.5* ( vSort[nSize/2] + vSort[nSize/2-1]));
		break;
	/// Hong 06/07/09 QA-13673 ADD_NEW_METHOD_SUM
	case method_sum:
		vv.Sum(dNormalizeVal);
		break;
	/// end ADD_NEW_METHOD_SUM
	case method_sd:
		nRet = ocmath_basic_summary_stats(vv.GetSize(), vv, NULL, NULL, &dNormalizeVal);
		break;
	case method_norm:
		double 		dNorm;
		vector 		vTmp;
		vTmp = vv * vv;
		vTmp.Sum(dNorm);
		dNormalizeVal = sqrt(dNorm);
		break;
	case method_mode:
		nRet = ocmath_opt_summary_stats(vv.GetSize(), vv, 0.95, &dNormalizeVal); //Here 0.95 doesn't make sense
		break;
	case method_ref:
		break;
	case method_pt:
		/// Iris 8/07/2009 QA80-13673  ADD_PICK_BUTTON_EVENTS
		///Sophy 8/17/2009 QA80-14087-P3 NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
		//if( NULL != pdPickY )
			//dNormalizeVal = *pdPickY;
		/// Iris 9/03/2009 QA80-13673-P13 DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
		/*
		if ( NULL != pdPickY && NULL != pPtsIndex )
		{
			ASSERT(*pdPickY != 0 && *pPtsIndex >= 0 && *pPtsIndex < vv.GetSize());
			dNormalizeVal = vv[*pPtsIndex]/(*pdPickY);
		}
		*/
		ASSERT( vSrcX && pdPickX );
		if ( vSrcX && pdPickX )
		{
			double dNewY;
			if( OE_NOERROR != ocmath_interpolate(pdPickX, &dNewY, 1, vSrcX, vv, vv.GetSize()) )
				ASSERT(false);
			if( is_equal(*pdPickY, 0) )
				dNormalizeVal = 0;
			else
				dNormalizeVal = dNewY / *pdPickY;
		}
		///end DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
		///end NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
		break;
		///end ADD_PICK_BUTTON_EVENTS
	default:
		return false;
	}
	return (STATS_NO_ERROR == nRet) ? true : false;
}

static double _get_use_column_reference_val(const vector& vv, int nNormalizeTo)
{
	double			dVal = NANUM, dSub;
	switch ( nNormalizeTo )
	{
	case to_min:
		_get_normalize_val(dVal, dSub, vv, method_min);
		break;
	case to_max:
		_get_normalize_val(dVal, dSub, vv, method_max);
		break;
	case to_mean:
		_get_normalize_val(dVal, dSub, vv, method_mean);
		break;
	case to_median:
		_get_normalize_val(dVal, dSub, vv, method_median);
		break;
	case to_sum:
		vv.Sum(dVal);
		break;
	}
	return dVal;
}
///---

///Sophy 10/12/2009 QA80-14087-P12 UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
//static void _on_pick_point_event(DataRange& drInput, double& pickx, double& picky, int& pickidx, WndContainer* pDynaCntrlContainer = NULL)
static bool _on_pick_point_event(DataRange& drInput, double& pickx, double& picky, int& pickidx, string& strRngStr, WndContainer* pDynaCntrlContainer = NULL)
///end UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
{
	/// Iris 8/07/2009 QA80-13673  ADD_PICK_BUTTON_EVENTS
	Window wnd;
	if( pDynaCntrlContainer )
	{
		HWND hwnd = GetWindow();
		Window wndTemp(hwnd);
		wnd.Attach(wndTemp);
		if( wnd )
		{
			// to hide normalize dialog
			pDynaCntrlContainer->ShowWindow(SW_HIDE);      
			wnd.Enable = TRUE;
		}
	}
	
	bool bOK = false;
	// open get points dialog
	GraphLayer gl = Project.ActiveLayer();
	///Sophy 8/18/2009 QA80-13673-P9 CNORMALIZE_FAIL_TO_SELECT_REFER_POINT_WHEN_CHANGE_PARAMETER
	if ( !gl ) //graph should be active
	{
		vector<uint>	vnPlotUIDs;
		if ( drInput && drInput.GetPlots(vnPlotUIDs) > 0 )
		{
			DataPlot dp;
			dp = (DataPlot)Project.GetObject((int)vnPlotUIDs[0]);
			if ( dp )
			{
				dp.GetParent(gl);
				gl.CheckShowActivate();
			}
		}
	}
	///end CNORMALIZE_FAIL_TO_SELECT_REFER_POINT_WHEN_CHANGE_PARAMETER
	int nPlotIndex = -1; 
	vector vx, vy;
	///Sophy 8/17/2009 QA80-14087-P2 SHOW_USEFUL_MSG_ON_GET_PTS_DIALOG
	//if( 1 == graph_get_points(vx, vy, NULL, NULL, &nPlotIndex, NULL, 1) && vy.GetSize() > 0 )
	vector<int> vPtsIndices;
	///Sophy 10/12/2009 QA80-14087-P12 UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
	//if( 1 == graph_get_points(vx, vy, NULL, NULL, &nPlotIndex, NULL, 1, -1, vPtsIndices, false) && vy.GetSize() > 0 )
	vector<int> vPlotIndices;
	if( 1 == graph_get_points(vx, vy, NULL, NULL, &nPlotIndex, NULL, 1, -1, vPtsIndices, false, vPlotIndices) && vy.GetSize() > 0 )
	///end UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
	///end SHOW_USEFUL_MSG_ON_GET_PTS_DIALOG
	{
		bOK = true;
		pickx = vx[0]; ///Sophy 8/17/2009 QA80-14087-P2 SHOW_USEFUL_MSG_ON_GET_PTS_DIALOG
		picky = vy[0];
		/// Iris 9/03/2009 QA80-13673-P13 DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
		//trGetN.pickidx.nVal = vPtsIndices[0] - 1;///Sophy 8/17/2009 QA80-14087-P2 SHOW_USEFUL_MSG_ON_GET_PTS_DIALOG return value is 1-offset, convert to 0-offset
		pickidx = vPtsIndices[0]; // should keep 1 offset on GUI
		///end DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
		///Sophy 10/12/2009 QA80-14087-P12 UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
		DataPlot dp = gl.DataPlots(vPlotIndices[0]);
		if ( dp )
		{
			dp.GetRangeString(strRngStr, NTYPE_BOOKSHEET_XY_RANGE);
			strRngStr.Format("%s[%d:%d]", strRngStr, pickidx, pickidx);
		}
		///end UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
	}
		
	// to show normalize dialog
	if( pDynaCntrlContainer )
	{
		wnd.Enable = FALSE;
		pDynaCntrlContainer->ShowWindow(SW_SHOW);
		pDynaCntrlContainer->Enable = TRUE;
	}
	
	///end ADD_PICK_BUTTON_EVENTS	
	return bOK;
}

///------ Folger 11/05/09 QA81-14087-P24 FAILS_TO_CREATE_OP_WHEN_PICK_REF_POINT_WITH_EVEN_SAMPLING_INPUT
static	void	_check_update_refpoint_range_string(TreeNode& trGetN)
{
	DataRange	xy;
	TreeNode	trRefPoint = trGetN.refpoint;
	if (okxf_resolve_tree_construct_range(&trRefPoint, &xy) )
	{
		int		nNumRanges = xy.GetNumRanges();
		if ( nNumRanges != 2 )
			return;
		
		Worksheet	wks;
		int			c1, c2;
		xy.GetRange(wks, c1, c2);
		if ( wks && c1 == 0 && c2 == -1 )
		{
			int		r1, r2;
			string	strName;
			xy.GetRange(1, r1, c1, r2, c2, wks, &strName);
			DataRange	drTemp;
			drTemp.Add(strName, wks, r1, c1, r2, c2);
			
			string		strRange;
			drTemp.GetRangeString(strRange);
			trRefPoint.strVal = strRange;
		}
	}
}
///------ End FAILS_TO_CREATE_OP_WHEN_PICK_REF_POINT_WITH_EVEN_SAMPLING_INPUT


void cnormalize(const XYRange& iy, const TreeNode& datainfo, const int& method, const double& val, const XYRange& ref, const int& to, const int& pick, const double& pickx, const double& picky, const int& pickidx, const Range& refpoint, XYRange& oy)
{
	///--- Hong, for temp
	DWORD 	dwRules = DRR_GET_MISSING | DRR_BAD_WEIGHT_TREATMENT | DRR_GET_DEPENDENT;
	int		nNumSrcData = iy.GetNumData(dwRules);
	int		nNumDestData = oy.GetNumData(dwRules);
	if ( nNumSrcData != nNumDestData )
		XF_THROW(XFERR_OUTPUT_DATA_NUMBER_NOT_THE_SAME_AS_INPUT);
	
	Column colRef; ///Sophy 9/2/2009 IMPROVE_COMMENTS_FOR_NORMALIZE_RESULT_COLUMNS
	
	///Sophy 8/18/2009 QA80-14087-P5 CURVE_NORMALIZE_GET_WRONG_RESULT_WHEN_REFER_TO_COLUMN
	double	dRefVal = val;
	if ( method_ref == method )
	{
		vector vRefX, vRefY;
		if ( !ref || !ref.GetData(vRefY, vRefX, NULL, 0, dwRules) )
			XF_THROW(CER_INVALID_XYRANGE);
		dRefVal = _get_use_column_reference_val(vRefY, to);
		
		ref.GetYColumn(colRef, 0); ///Sophy 9/2/2009 IMPROVE_COMMENTS_FOR_NORMALIZE_RESULT_COLUMNS only one Y range, so just get the first one
	
	}
	///end CURVE_NORMALIZE_GET_WRONG_RESULT_WHEN_REFER_TO_COLUMN
	///Iris 9/18/2009 SUPORT_PICK_POINT_METHOD_FOR_SCRIPT_MODE
	else if( method_pt == method )
	{
		///Sophy 4/13/2010 CHOOSE_MASKED_POINT_ON_GRAPH_AS_REFER_POINT_AND_RECALCULATE
		//if( is_missing_value(pickx) || is_missing_value(picky) || 0 == pickidx ) // not choose any point, means this case from script mode, so need open pick point dialog to choose.
		if ( 0 == pickidx ) //when choose masked point, picky might be missing value, only need to check index.
		///end CHOOSE_MASKED_POINT_ON_GRAPH_AS_REFER_POINT_AND_RECALCULATE
		{
			string strRngStr;
			_on_pick_point_event(iy, pickx, picky, pickidx, strRngStr);
		}
	}
	///end SUPORT_PICK_POINT_METHOD_FOR_SCRIPT_MODE
	
	for ( int ii = 0; ii < nNumSrcData; ii++ )
	{
		vector		vSrcX, vSrcY;
		if ( !iy.GetData(vSrcY, vSrcX, NULL, ii, dwRules) )
			XF_THROW(CER_INVALID_XYRANGE);
		
		///Sophy 8/18/2009 QA80-14087-P5 CURVE_NORMALIZE_GET_WRONG_RESULT_WHEN_REFER_TO_COLUMN
		//double		dVal = val;
		//if ( method_ref == method )
		//{
			//vector	vRefX, vRefY;
			//if ( !ref || !iy.GetData(vRefY, vRefX, NULL, 0, dwRules) )
				//XF_THROW(CER_INVALID_XYRANGE);
			//dVal = _get_use_column_reference_val(vRefY, to);
		//}
		double		dVal = val;
		if ( method_ref == method )
		{
			///Sophy 8/31/2009 FIX_NORMALIZE_WITH_MINUS_VALUE_GET_INCORRECT_RESULT
			//dVal = _get_use_column_reference_val(vSrcY, to);
			dVal = _get_use_column_reference_val(vSrcY, to);
			if ( to == to_min && dVal * dRefVal  < 0 )
				dVal = _get_use_column_reference_val(vSrcY, to_max);
			else if ( to == to_max && dVal * dRefVal < 0 )
				dVal = _get_use_column_reference_val(vSrcY, to_min);
			///end FIX_NORMALIZE_WITH_MINUS_VALUE_GET_INCORRECT_RESULT
			dVal = (is_equal(0.0, dRefVal) ? NANUM : (dVal/dRefVal));
			
		}
		///end CURVE_NORMALIZE_GET_WRONG_RESULT_WHEN_REFER_TO_COLUMN
		
		/// Iris 8/07/2009 QA80-13673  ADD_PICK_BUTTON_EVENTS
		//if ( 0 != _normalize_data(vSrcY, method, dVal) )
		///Sophy 8/17/2009 QA80-14087-P3 NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
		//if ( 0 != _normalize_data(vSrcY, method, dVal, picky) )
		/// Iris 9/03/2009 QA80-13673-P13 DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
		//if ( 0 != _normalize_data(vSrcY, method, dVal, picky, pickidx) )
		if ( 0 != _normalize_data(vSrcY, method, dVal, vSrcX, pickx, picky) )
		///end DO_LINEAR_INTEPOLATE_ON_SOURCE_DATA_REFER_TO_PICKED_POINT
		///end NORMALIZE_WITH_SELECTED_POINT_FROM_GRAPH_GET_WRONG_RESULT
		///end ADD_PICK_BUTTON_EVENTS
			XF_THROW(XFERR_INVALID_ARG);
		///Kyle 08/19/2009 QA80-14023 FIX_OUTPUT_SAMPLING_INTERVAL_IS_LOST_WHEN_INPUT_IS_LOOSE_DATASET
		//oy.SetData(&vSrcY, &vSrcX, ii);		
		///Kyle 09/22/2009 QA80-14023 FIX_SAMPLING_IS_NOT_RESET_IF_SET_INPUT_AS_OUTPUT
		//set_xyrange_data_ex(oy, &vSrcY, &vSrcX, ii, iy);
		/// YuI 09/30/09 QA70-14399 UNNECESARY_AUTOUPDATE_IN_CASE_OF_INPUT_NEW
		//	set_xyrange_data_ex(oy, &vSrcY, &vSrcX, ii);
		
		// reverting Kyle's change
		// fixed in update_output_xyrange_even_sampling which is called from set_xyrange_data_ex
		set_xyrange_data_ex(oy, &vSrcY, &vSrcX, ii, iy);
		/// end UNNECESARY_AUTOUPDATE_IN_CASE_OF_INPUT_NEW
		///End FIX_SAMPLING_IS_NOT_RESET_IF_SET_INPUT_AS_OUTPUT
		///End FIX_OUTPUT_SAMPLING_INTERVAL_IS_LOST_WHEN_INPUT_IS_LOOSE_DATASET
		
		/// Iris 8/13/2009 QA80-13673-P8 ADD_COMMENTS_IN_RESULT_COL
		Column colOutY;		
		if( oy.GetYColumn(colOutY, ii))
		{
			///Sophy 9/2/2009 IMPROVE_COMMENTS_FOR_NORMALIZE_RESULT_COLUMNS
			//string strMethod = normalize_get_method_string(method, val, to);
			///Sophy 9/15/2009 IMPROVE_COMMENTS_FOR_NORMALIZE_RESULT_COLUMNS
			//string strMethod = normalize_get_method_string(method, val, to, colRef, XF_CNORMALIZE);
			string strRange = get_xy_range_string(iy, "Y", ii);
			string strComments = normalize_get_method_string(strRange, method, val, to, colRef, XF_CNORMALIZE);
			///end IMPROVE_COMMENTS_FOR_NORMALIZE_RESULT_COLUMNS
			///end IMPROVE_COMMENTS_FOR_NORMALIZE_RESULT_COLUMNS
			
			///Sophy 9/15/2009 IMPROVE_COMMENTS_FOR_NORMALIZE_RESULT_COLUMNS
			//string strComments;
			//strComments.Format("%s of %s", strMethod, strRange);
			///end IMPROVE_COMMENTS_FOR_NORMALIZE_RESULT_COLUMNS
			colOutY.SetComments(strComments);
		}
		///end ADD_COMMENTS_IN_RESULT_COL
	}
	///Sophy 8/31/2009 QA80-14087-S1 PLOT_RESULT_CURVES_ON_SOURCE_GRAPH
	if ( oy )
	{
		vector<uint> dpSrcUIDs;
		if ( iy.GetPlots(dpSrcUIDs) > 0 )
		{
			///Sophy 10/22/2009 QA80-14087-S4 PLOT_EACH_RESULT_ON_SOURCE_GRAPHLAYER_AS_INPUT
			//dpSrc = (DataPlot)Project.GetObject(dpSrcUIDs[0]);
			//GraphLayer gl;
			//dpSrc.GetParent(gl);
			//int nPlotType = dpSrc.GetPlotType();
			//int nPlot = plot_data_range(oy, gl, nPlotType, GAP_USE_TEMPLATE | GAP_GROUP_PLOTS, NULL, true);
			//legend_update(gl);
			for ( int iPlot = 0; iPlot < dpSrcUIDs.GetSize(); iPlot++ )
			{
				DataPlot dpSrc;
				dpSrc = (DataPlot)Project.GetObject(dpSrcUIDs[iPlot]);
				//in VC level code COKPolyRange::AddToRange, even if Plot UID is invliad/unknown, still added into UID array
				//so here we need to check whether it is a valid Plot UID
				if ( dpSrc )
				{
					GraphLayer glSrc;
					dpSrc.GetParent(glSrc);
					int nSrcPlotType = dpSrc.GetPlotType();
					
					DataRange drSub;
					if ( oy.GetSubRange(drSub, DRR_GET_DEPENDENT | DRR_NO_FACTORS, iPlot) )
					{
						XYRange drOneXY(drSub);
						int nPlot = plot_data_range(drOneXY, glSrc, nSrcPlotType, GAP_USE_TEMPLATE | GAP_GROUP_PLOTS, NULL, true);
						DataPlot dpResult = glSrc.DataPlots(nPlot);
						dpResult.SetColor(SYSCOLOR_RED);
						legend_update(glSrc);
					}
				}
			}
			///end PLOT_EACH_RESULT_ON_SOURCE_GRAPHLAYER_AS_INPUT
		}
	}
	///end PLOT_RESULT_CURVES_ON_SOURCE_GRAPH
	return ;
	///---	
}

//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 cnormalize_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return cnormalize_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	/// Iris 10/09/2009 HIDDEN_TOTAL_DATA_INFO_ON_GUI
	/*
	bool bIsChangingData = lstrcmpi(lpcszNodeName,"iy") == 0? true:false;
	if(GETNE_ON_INIT == nEventID || bIsChangingData)
	{
		/// Iris 8/07/2009 QA80-13673-S1 ADD_TOTAL_DATA_INFO_GUI_TREE
		XYRange xyTemp;
		TreeNode trXY = trGetN.iy;
		okxf_resolve_tree_construct_range(&trXY, &xyTemp);
		
		vector vTotalY;
		///Sophy 9/10/2009 QA80-14087-P15 CNORMALIZE_GET_DATA_FROM_PLOT_SHOULD_GET_MISSING_VALUES
		//int nNumData = xyTemp.GetNumData();
		DWORD dwDataRules = DRR_GET_DEPENDENT | DRR_GET_MISSING;
		int nNumData = xyTemp.GetNumData(dwDataRules);
		///end CNORMALIZE_GET_DATA_FROM_PLOT_SHOULD_GET_MISSING_VALUES
		for(int nn=0; nn < nNumData; nn++)
		{
			vector 	vy, vx;
			///Sophy 9/10/2009 QA80-14087-P15 CNORMALIZE_GET_DATA_FROM_PLOT_SHOULD_GET_MISSING_VALUES
			//xyTemp.GetData(vy, vx, NULL, nn);
			xyTemp.GetData(vy, vx, NULL, nn, dwDataRules);
			///end CNORMALIZE_GET_DATA_FROM_PLOT_SHOULD_GET_MISSING_VALUES
			vTotalY.Append(vy);
		}		
		normalize_set_datainfo(vTotalY, trGetN.datainfo);
		///end ADD_TOTAL_DATA_INFO_GUI_TREE
	}
	*/
	///end HIDDEN_TOTAL_DATA_INFO_ON_GUI
	
	/// Iris 9/01/2009 QA80-13673-P4 FIX_REF_PLOT_EFFECT_AU_EVEN_IT_IS_HIDDEN
	if( GETNE_ON_INIT == nEventID || 0 == lstrcmpi(lpcszNodeName, "ref") )
	{		
		string strData;
		if( trGetN.ref.GetAttribute(STR_DATA_ATTRIB, strData) && PDS_OPTIONAL != str_to_predefined_type(strData) )
			trGetN.ref.SetAttribute(STR_REF_PLOT_OLD_VAL, strData);
	}
	///end FIX_REF_PLOT_EFFECT_AU_EVEN_IT_IS_HIDDEN
	
	bool bIsChangingOption = lstrcmpi(lpcszNodeName, "method") == 0? true:false;
	if(GETNE_ON_INIT == nEventID || GETNE_ON_THEME == nEventID || bIsChangingOption) // should consider theme case
	{
		//_initial_method_show(trGetN);
		trGetN.val.Show = (trGetN.method.nVal == method_specify) ? true : false;	/// Max 11/25/08 v8.0975d SHARE_SAME_FUNC_FOR_NORMALIZE_AND_VNORMALIZE
		bool		bUseReferencePlot = (method_ref == trGetN.method.nVal) ? true : false;
		trGetN.ref.Show = bUseReferencePlot;
		trGetN.to.Show = bUseReferencePlot;
		trGetN.pick.Show = (method_pt == trGetN.method.nVal) ? true : false;		
		trGetN.pickx.Show = trGetN.pick.Show; ///Sophy 8/17/2009 QA80-14087-P2 SHOW_USEFUL_MSG_ON_GET_PTS_DIALOG
		trGetN.picky.Show = trGetN.pick.Show; /// Iris 8/07/2009 QA80-13673  ADD_PICK_BUTTON_EVENTS
		trGetN.pickidx.Show = trGetN.pick.Show; ///Sophy 8/17/2009 QA80-14087-P2 SHOW_USEFUL_MSG_ON_GET_PTS_DIALOG
		
		/// Iris 9/01/2009 QA80-13673-P4 FIX_REF_PLOT_EFFECT_AU_EVEN_IT_IS_HIDDEN
		_check_reset_ref_plot(trGetN.ref, trGetN.method.nVal, method_ref, STR_REF_PLOT_OLD_VAL);
		///end FIX_REF_PLOT_EFFECT_AU_EVEN_IT_IS_HIDDEN
	}	
	
	if ( 0 == lstrcmpi(lpcszNodeName, "pick") )
	{
		DataRange drInput;
		drInput.Create();
		drInput.SetTree(trGetN.iy);
		double dx, dy;
		int index;
		string strRefRng;
		///Sophy 10/12/2009 QA80-14087-P12 UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
		//_on_pick_point_event(drInput, dx, dy, index, &DynaCntrlContainer);
		if ( _on_pick_point_event(drInput, dx, dy, index, strRefRng, &DynaCntrlContainer) )
		{
			trGetN.refpoint.strVal = strRefRng;
			trGetN.pickx.dVal = dx;
			trGetN.picky.dVal = dy;
			trGetN.pickidx.nVal = index;
		}
		///end UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
	}	
	///Sophy 10/12/2009 QA80-14087-P12 UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
	if ( GETNE_ON_INIT == nEventID && lstrcmp(lpcszNodeName, "pick") != 0 || lstrcmp(lpcszNodeName, "method") == 0 )
	{
		double dx, dy;
		if ( _update_ref_point_from_range(trGetN.refpoint.strVal, dx, dy) )
		{
			trGetN.pickx.dVal = dx;
			trGetN.picky.dVal = dy;
		}
	}
	///end UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
	int nErr = _check_err_condition(trGetN);
	
	if(nErr != CER_NO_ERROR)
	{
		bOKEnable = false;
		strErrMsg = nErr;
	}	
	
	return true;

}

int cnormalize_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	
	return normalize_make_datainfo_tree(tr, lpcszVarName);
	
}
//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 cnormalize_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	///--- Hong, for temp
	if ( nGetNDialog >0 )
	{
		TreeNode trBtns = trGetN.pick;
		trBtns.SetAttribute(STR_ID_ATTRIB, ONODETYPE_PUSHBUTTON_GROUP);
		trBtns.SetAttribute(STR_COMBO_ATTRIB, _L("Pick Point"));			
		DWORD dwDisplyBits = DISPLAY_EDITOR_HORZ;
		trBtns.SetAttribute(STR_ATTRIB_DISPFMT, (string)dwDisplyBits);
		///Sophy 8/17/2009 QA80-14087-P4 READ_ONLY_NODE_WITH_BETTER_DISPLAY
		//trGetN.picky.Enable = false; /// Iris 8/07/2009 QA80-13673  ADD_PICK_BUTTON_EVENTS
		trGetN.pickx.Enable = 2;
		trGetN.picky.Enable = 2;
		trGetN.pickidx.Enable = 2;
		///end READ_ONLY_NODE_WITH_BETTER_DISPLAY
		trGetN.datainfo.Show = false; /// Iris 10/09/2009 HIDDEN_TOTAL_DATA_INFO_ON_GUI
	}	
	
	if( nGetNDialog == -1 || nGetNDialog == 0 )
	{
		///------ Folger 08/02/10 ORG-672 INTEG1_SUPPORT_MULTIPLE_XYRANGES
		//if( 1 == trGetN.oy.GetNodeCount() )
		//{
			///// YuI 07/09/09 QA70-13915 PROPER_SUPPORT_FOR_OUTPUT_MULTIDATA_XYRANGE
			///*
			//// Hong, to do, more check need to be done, like support [input]<new>!(<input>, <new>)
			//int				nType = okutil_cvt_str_to_predefined_type(trGetN.oy.Range1.Y.strVal);
			//if( PDS_NEW == nType || PDS_INPUT == nType )
			//{
				//int nNeededNumberOfData = trGetN.iy.GetNodeCount();
				//for( int ii = 1; ii < nNeededNumberOfData; ii++ )
				//{
					//string strName = "Range" + (ii + 1);
					//TreeNode trTemp = trGetN.oy.AddNode(strName);
					//trTemp.Replace(trGetN.oy.Range1.Clone(), TRUE, TRUE);
				//}
			//}
			//*/
			//TreeNode trInput = trGetN.iy;
			//TreeNode trOutput = trGetN.oy;
			//okutil_prepare_multiXY_output_tree(&trOutput, &trInput, 0);
			///// end PROPER_SUPPORT_FOR_OUTPUT_MULTIDATA_XYRANGE
		//}
		prepare_multixy_output_tree(trGetN.iy, trGetN.oy);
		///------ End INTEG1_SUPPORT_MULTIPLE_XYRANGES
		//if click ok and the method is NOT refer to point on graph, should make refpoint as optional, or else in XF body refpoint is VALID range
		//and will cause output problems
		if ( trGetN.method.nVal != method_pt )
		{
			trGetN.refpoint.strVal = STR_OPTIONAL;
			///Sophy 10/22/2009 QA80-14087-P19 FORCE_NOT_REMEMBER_REF_POINT_SETTINGS_WHEN_METHOD_NOT_REF_TO_POINT
			trGetN.pickidx.strVal = STR_UNASSIGNED;
			trGetN.pickx.strVal = STR_UNASSIGNED;
			trGetN.picky.strVal = STR_UNASSIGNED;
			///end FORCE_NOT_REMEMBER_REF_POINT_SETTINGS_WHEN_METHOD_NOT_REF_TO_POINT
		}
		///end UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
		///------ Folger 11/05/09 QA81-14087-P24 FAILS_TO_CREATE_OP_WHEN_PICK_REF_POINT_WITH_EVEN_SAMPLING_INPUT
		else
		{
			_check_update_refpoint_range_string(trGetN);
		}
		///------ End FAILS_TO_CREATE_OP_WHEN_PICK_REF_POINT_WITH_EVEN_SAMPLING_INPUT
	}
	///---
		
	///Sophy 10/12/2009 QA80-14087-P12 UPDATE_REFER_POINT_FOR_RECALCULATE_CHANGE_PARAMS
	if ( 0 == nGetNDialog && trGetN.method.nVal == method_pt )
	{
		double dx, dy;
		if ( _update_ref_point_from_range(trGetN.refpoint.strVal, dx, dy) )
		{
			trGetN.pickx.dVal = dx;
			trGetN.picky.dVal = dy;
		}
	}
	//------ fisher 11/16/07 ADD_MAP_ID_TO_CHM
	if(is_use_origin_chm())
		trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_XF_normalize);	
	
	///Cheney 2007-6-7 ADD_AN_ERR_CHECK_FUNC
	///Cheney 2007-6-14 PROCEED_WITH_DLG_SHOULD_IF_ERR
	//if(0 == nGetNDialog && (dwCntrl&LTXF_THEME_USED) && _check_err_condition(trGetN) != CER_NO_ERROR)
	if(0 == nGetNDialog && (dwCntrl&LTXF_THEME_USED) && (dwCntrl&LTXF_FROM_GUI_MENU)
		&& _check_err_condition(trGetN) != CER_NO_ERROR)
	///end PROCEED_WITH_DLG_SHOULD_IF_ERR
		nRet = XFEVT_PROCEED_WITH_DLG;	
	///end ADD_AN_ERR_CHECK_FUNC
	
}
//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 cnormalize_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	/// Folger 11/05/09 in order to clear the fake "Cursor" icon in graph
	if ( GETNE_ON_DESTORY == nEventID )
	{
		GraphPage	gp = Project.Pages();
		if ( gp )
		{
			gp.Refresh();
		}
		return true;
	}
	
	return false;
}
