#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>

//put additional include files here
#include <..\Originlab\XFunctionEx.h>

/*------------------------------------------------------------------------------*
 * Modification Log:															*
 * Echo 2007-8-3 CLEAN_BAD_CODES												*
 * Echo 12/11/2007 	RESCALE_ONLY_AVAIABLE_IN_GRAPH								*	
 * Kyle 10/31/08 QA80-12146 PREVENT_SUBTRACTING_DATA_FROM_ITSELF 				*
 * Kyle 12/22/2008 FIX_RUNTIME_ERROR_WHEN_INPUT_HAS_SAMPLING_INTERVAL			*
 * Kyle 02/19/2009 QA80-12146-P1 BETTER_MESSAGE_FOR_INPUTS_INTERSECTION			*
 * Kyle 02/19/2009 QA80-12146 UNDO_BETTER_MESSAGE_FOR_INPUTS_INTERSECTION		*
 * Kyle 02/24/2009 QA80-13169 CHECK_IF_TWO_RANGE_HAVE_COMMON_RANGE				*
 *------------------------------------------------------------------------------*/

 
//------ Folger 08/13/07 CORRECT_SUBTRACT_OPERATOR
//#define operator_Subtract	2
#define operator_Subtract	1
//------ Folger 08/13/07 CORRECT_SUBTRACT_OPERATOR
#define operand_RefData		1

///Kyle 02/19/2009 QA80-12146 UNDO_BETTER_MESSAGE_FOR_INPUTS_INTERSECTION
/////Kyle 10/31/08 QA80-12146 PREVENT_SUBTRACTING_DATA_FROM_ITSELF 
//static bool check_if_two_range_intersect(TreeNode & trGetN)
//{
	//DataRange rng1, rng2;
	//TreeNode trRange1, trRange2;
	//trRange1 = trGetN.iy1;
	//trRange2 = trGetN.iy2;
	//okxf_resolve_tree_construct_range(&trRange1, &rng1);
	//okxf_resolve_tree_construct_range(&trRange2, &rng2);
	//DataRange Yrng1, Yrng2;
	//int r1, c1, r2, c2;
	//Worksheet wks;
	/////Kyle 12/22/2008 FIX_RUNTIME_ERROR_WHEN_INPUT_HAS_SAMPLING_INTERVAL
	////rng1.GetRange( 1, r1, c1, r2, c2, wks);
	//rng1.GetRange( "Y", r1, c1, r2, c2, wks );
	/////End FIX_RUNTIME_ERROR_WHEN_INPUT_HAS_SAMPLING_INTERVAL
	//Yrng1.Add( "Y", wks, r1, c1, r2, c2 );
//
	/////Kyle 12/22/2008 FIX_RUNTIME_ERROR_WHEN_INPUT_HAS_SAMPLING_INTERVAL
	////rng2.GetRange( 1, r1, c1, r2, c2, wks);
	//rng2.GetRange( "Y", r1, c1, r2, c2, wks);
	/////End FIX_RUNTIME_ERROR_WHEN_INPUT_HAS_SAMPLING_INTERVAL
	//Yrng2.Add( "Y", wks, r1, c1, r2, c2 );
//
	//if(Yrng1.Intersects(Yrng2))
		//return true;
	//return false;
//}
/////End PREVENT_SUBTRACTING_DATA_FROM_ITSELF
///End UNDO_BETTER_MESSAGE_FOR_INPUTS_INTERSECTION




void subtract_ref(const XYRange& iy1, const XYRange& iy2, const int& common, const int& rescale, XYRange& oy, double& xmin, double& xmax, double& xmean, double& ymin, double& ymax, double& ymean)
{
	
	///Echo 2007-8-3 CLEAN_BAD_CODES
	///The function should call mathtool.oxf instead of copying it's code here
	XFBase	xf("mathtool");
	if ( !xf )
		XF_THROW(XFERR_FAIL_LOAD_XF);
	//if ( !xf.SetArgs(r, ellipse, conflevel,0, missing, rd, rtPlot) ) 
	if ( !xf.SetArgs(iy1, operator_Subtract, operand_RefData, iy2, 0, common, rescale, oy) )
		XF_THROW(XFERR_FAIL_SET_ARG);
	if ( !xf.Evaluate() )
		XF_THROW(XFERR_FAIL_EVAL);	
		
	//xf_check_plot_output_rng_in_source_rng_graph(iy1, oy);
	
	
	/*
	vector vx1, vy1, vx2, vy2;
	
	if (iy1.GetData(vy1, vx1)) 
	{
		if(0 == vy1.GetSize() || 0 == vx1.GetSize())
		{
			XF_THROW(CER_DATA_TOO_FEW);
		}
	}
	else
	{
		XF_THROW(XFERR_GET_DATA_FAILED);
	}
	
	//bool bNotMonotonic = false;
	///Folger 06/19/07 IMPROVEMENT_SUBTRACT_REF
	//if (!operand)
	//{
	///End IMPROVEMENT_SUBTRACT_REF
		if(iy2.GetData(vy2, vx2))
		{
			if(0 == vy2.GetSize() || 0 == vx2.GetSize())
			{
				XF_THROW(CER_DATA_TOO_FEW);
			}
		}
		else
		{
			XF_THROW(CER_DATA_TOO_FEW);
		}
		//bNotMonotonic = MONO_NOT == ocmath_is_monotonic(vx2, vx2.GetSize(), false);
	///Folger 06/19/07 IMPROVEMENT_SUBTRACT_REF
	//}else
	//{
		//vx2.SetSize(vx1.GetSize());
		//vy2.SetSize(vy1.GetSize());
		//switch(dir)
		//{
		//case 0:
			//vx2 = vx1;
			//vy2 = const;
			//break;
		//case 1:
			//vx2 = const;
			//vy2 = vy1;
			//break;
		//}
		//
	//}
	///End IMPROVEMENT_SUBTRACT_REF
	//if ( MONO_NOT == ocmath_is_monotonic(vx1, vx1.GetSize(), false) ||  bNotMonotonic)
	//{
		//warning_msg_box(CWARN_NONMONOTONIC_X, true);
		//vector<uint> vnIndeces;
		//vx1.Sort(SORT_ASCENDING, TRUE, vnIndeces);
		//vy1.Reorder(vnIndeces);
		//vx2.Sort(SORT_ASCENDING, TRUE, vnIndeces);
		//vy2.Reorder(vnIndeces);
	//}
	
	int nSize1 = vx1.GetSize();
	int nSize2 = vx2.GetSize();
	vector vOutX(nSize1), vOutY(nSize1);
	vOutX = NANUM;  
	vOutY = NANUM;
	//switch(dir)
	//{
	/////Folger 06/19/07 IMPROVEMENT_SUBTRACT_REF
	////case 0:
	//case dir_Y:
	/////End IMPROVEMENT_SUBTRACT_REF
		//ocmath_simple_math(nSize1, vOutX, vOutY, nSize1, vx1, vy1, nSize2, vx2, vy2, MATHTOOL_OPT_SUB, common);
		//break;
	/////Folger 06/19/07 IMPROVEMENT_SUBTRACT_REF
	////case 1:
	//case dir_X:
	/////End IMPROVEMENT_SUBTRACT_REF
		//ocmath_simple_math(nSize1, vOutY, vOutX, nSize1, vy1, vx1, nSize2, vy2, vx2, MATHTOOL_OPT_SUB, common);
		//break;
	//}
	ocmath_simple_math(nSize1, vOutX, vOutY, nSize1, vx1, vy1, nSize2, vx2, vy2, MATHTOOL_OPT_SUB, common);
	vOutX.Trim();
	vOutY.Trim();
	if(oy.SetData(&vOutY, &vOutX))
	{
		///Folger 06/20/07 NO_NEED
		//DataPlot dp = oy.MakePlot(iy1);
		//if (dp)
		//{
			////dp.SetColor(color);		///Folger 06/19/07 IMPROVEMENT_SUBTRACT_REF
			//GraphLayer gl;
			//dp.GetParent(gl);
			//gl.Rescale();
		//}
		///End NO_NEED
	}
	*/
	///end CLEAN_BAD_CODES
	
			
	//Output stats values
	vector vx1, vy1;
	oy.GetData(vy1, vx1);
	vx1.GetMinMax(xmin, xmax);
	vy1.GetMinMax(ymin, ymax);
	vx1.Sum(xmean);
	xmean /= vx1.GetSize();
	vy1.Sum(ymean);
	ymean /= vy1.GetSize();
	
	//LT_execute("legend -s");
	
	
}

//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 subtract_ref_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return subtract_ref_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	///Folger 06/19/07 IMPROVEMENT_SUBTRACT_REF
	//bool bShowXYRange = false;
	//bool bShowConstant = false;	
	//switch(trGetN.operand.nVal)
	//{
		//case 0:
			//bShowXYRange = true;
			//break;
		//case 1:
			//bShowConstant = true;
			//break;
	//}
	//trGetN.iy2.Show = bShowXYRange;
	//trGetN.const.Show = bShowConstant;
		
	//if (!bShowXYRange)
	//{
		//trGetN.range.nVal = false;
		//trGetN.iy2.SetAttribute("Data", STR_OPTIONAL);	
	//}
	//trGetN.range.Enable = bShowXYRange;
		
	//GraphLayer gl = Project.ActiveLayer();
	//if(!gl.IsValid())
		//trGetN.color.Show = false;
	///End IMPROVEMENT_SUBTRACT_REF
	
	///Folger 06/20/07 USE_V_OPTION_STRING
	//trGetN.xmin.Show = false;
	//trGetN.xmax.Show = false;
	//trGetN.xmean.Show = false;
	//trGetN.ymin.Show = false;
	//trGetN.ymax.Show = false;
	//trGetN.ymean.Show = false;
	///End USE_V_OPTION_STRING
	
	///Echo 12/11/2007 	RESCALE_ONLY_AVAIABLE_IN_GRAPH
	XYRange xyTemp;
	bool bOK = xy_range_from_GetN_data_node(trGetN.iy1, xyTemp);
	if(bOK && xyTemp.IsValid())
	{
		vector<uint> vnUID;
		xyTemp.GetPlots(vnUID);
		trGetN.rescale.Enable = ( vnUID[0] <= 0 ) ? false : true;
	}
	///END RESCALE_ONLY_AVAIABLE_IN_GRAPH
	
	int nErr = CER_NO_ERROR;
	///Folger 06/19/07 IMPROVEMENT_SUBTRACT_REF
	//if(get_input_xyrange_num(trGetN.iy1) != 1 || get_input_xyrange_num(trGetN.iy2) != 1 && bShowXYRange)
	if(get_input_xyrange_num(trGetN.iy1) != 1 || get_input_xyrange_num(trGetN.iy2) != 1)
	///End IMPROVEMENT_SUBTRACT_REF
		nErr = CER_NOT_ONE_XYRANGE;
	///Kyle 02/19/2009 QA80-12146 UNDO_BETTER_MESSAGE_FOR_INPUTS_INTERSECTION
	/////Kyle 10/31/08 QA80-12146 PREVENT_SUBTRACTING_DATA_FROM_ITSELF 
	//else if(check_if_two_range_intersect(trGetN))
		/////Kyle 02/19/2009 QA80-12146-P1 BETTER_MESSAGE_FOR_INPUTS_INTERSECTION
		////nErr = XFERR_INVALID_RANGE;
		//nErr = XFERR_RANGE_INTERSECT;
		/////End BETTER_MESSAGE_FOR_INPUTS_INTERSECTION
	/////End PREVENT_SUBTRACTING_DATA_FROM_ITSELF
	///End UNDO_BETTER_MESSAGE_FOR_INPUTS_INTERSECTION
	
	///Kyle 02/24/2009 QA80-13169 CHECK_IF_TWO_RANGE_HAVE_COMMON_RANGE
	else if(trGetN.common.nVal && !have_common_range(trGetN.iy1, trGetN.iy2))
	{
		nErr = XFERR_NO_COMMON_RANGE;
		strErrMsg = nErr;
	}
	///End CHECK_IF_TWO_RANGE_HAVE_COMMON_RANGE
	
	
	
	if(nErr != CER_NO_ERROR)
	{
		bOKEnable = false;
		strErrMsg = nErr;
	}
	return true;
	

}

int subtract_ref_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 subtract_ref_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	if ((dwCntrl&LTXF_THEME_USED) && nGetNDialog <= 0)
	{
		bool bOKEnable; 
		if(get_input_xyrange_num(trGetN.iy1) != 1 || get_input_xyrange_num(trGetN.iy2) != 1 && trGetN.iy2.Show)
			nRet = XFEVT_PROCEED_WITH_DLG;		
		///Kyle 02/19/2009 QA80-12146 UNDO_BETTER_MESSAGE_FOR_INPUTS_INTERSECTION
		/////Kyle 10/31/08 QA80-12146 PREVENT_SUBTRACTING_DATA_FROM_ITSELF 
		//else if(check_if_two_range_intersect(trGetN))
			//nRet = XFEVT_PROCEED_WITH_DLG;
		/////End PREVENT_SUBTRACTING_DATA_FROM_ITSELF
		///End UNDO_BETTER_MESSAGE_FOR_INPUTS_INTERSECTION
	
	}
	
	
}
//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 subtract_ref_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
