#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	method_direct,
	method_xyz,
};
enum{
	xy_xcol,
	xy_ycol,
	xy_noxy,
};
enum{
	xlabel_none,
	xlabel_row1,
	xlabel_syspara,
	xlabel_userpara,
};
enum{
	ylabel_none,
	ylabel_row1,
	ylabel_syspara,
	ylabel_userpara,
};
enum{
	sysparam_p1,
	sysparam_p2,
	sysparam_p3,
	sysparam_p4,
	sysparam_p5,
	sysparam_p6,
	sysparam_p7,
	sysparam_p8,
	sysparam_p9,
	sysparam_p10,
};
enum{
	option_xconst,
	option_yconst,
};


//put additional include files here
#include <wks2mat.h>
//put your own support static functions here
/*
enum {
	M2W_DIRECT,
	M2W_XYZ_COLUMNS,
};

enum{
	X_ACROSS_COLUMNS,
	Y_ACROSS_COLUMNS,
	X_Y_UNCONSIDERED,
};
*/
enum{
	NONE,
	FIRST_ROW,
	SYSTEM_PARAMETERS,
	USER_DEFINED_PARAMETERS,
};

static void _update_parameter_show_by_type(TreeNode& trGetN, int nParamType)
{
	switch(nParamType)
	{
	case FIRST_ROW:
		trGetN.sysparam.Show = false;
		trGetN.userdef.Show = false;
		break;
	case SYSTEM_PARAMETERS:
		trGetN.sysparam.Show = true;
		trGetN.userdef.Show = false;
		break;
	case USER_DEFINED_PARAMETERS:
		trGetN.sysparam.Show = false;
		trGetN.userdef.Show = true;
		break;
	default:
		trGetN.sysparam.Show = false;
		trGetN.userdef.Show = false;
		break;
	}
}

static void _update_tree_show(TreeNode& trGetN)
{
	if (trGetN.method.nVal == method_xyz)
	{
		trGetN.option.Show = true;
		trGetN.xy.Show = false;
		trGetN.ycol.Show = false;
		trGetN.xlabel.Show = false;
		trGetN.xcol.Show = false;
		trGetN.ylabel.Show = false;
		trGetN.sysparam.Show = false;
		trGetN.userdef.Show = false;
	}
	
	if (trGetN.method.nVal == method_direct)
	{
		trGetN.option.Show = false;
		trGetN.xy.Show = true;
		int bXY = trGetN.xy.nVal;
		switch(bXY)
		{
		case xy_xcol:
			trGetN.ycol.Show = true;
			trGetN.xlabel.Show = true;
			int nParamType = trGetN.xlabel.nVal;
			_update_parameter_show_by_type(trGetN, nParamType);
			
			trGetN.xcol.Show = false;
			trGetN.ylabel.Show = false;
			break;
			
		case xy_ycol:
			trGetN.xcol.Show = true;
			trGetN.ylabel.Show = true;
			int nParamType = trGetN.ylabel.nVal;
			_update_parameter_show_by_type(trGetN, nParamType);
		
			trGetN.xrow.Show = false;
			trGetN.ycol.Show = false;
			trGetN.xlabel.Show = false;
			break;
		case xy_noxy:
			trGetN.xcol.Show = false;
			trGetN.ylabel.Show = false;
			_update_parameter_show_by_type(trGetN, NONE);
			trGetN.xrow.Show = false;
			trGetN.ycol.Show = false;
			trGetN.xlabel.Show = false;
			break;
			
		}
	}
	
}

static void _set_one_sys_parameter_value_col(Column& col, int index, string& strValue)
{
	col.SetParameter(strValue, index);
}

static bool _set_one_sys_parameter_values_wks(Worksheet& wks, vector& dParamValues, int nParamIndex = 0, int c1 = 0, int c2 = -1)
{
	if(c2 < 0)
		c2 = wks.GetNumCols()-1;
	
	if(c2 < c1)
		return false;
	
	for(int nCol = c1, ii = 0; nCol <= c2; nCol++, ii++)
	{
		Column col(wks, nCol);
		if(col)
		{
			string strValue = ftoa(dParamValues[ii]);
			_set_one_sys_parameter_value_col(col, nParamIndex, strValue);	
		}
		else
			return false;
	}
	
	return true;
}

static bool _set_one_user_defined_parameter_wks(Worksheet& wks, string& strParamName, vector& dParamValues, int c1 = 0, int c2 = -1)
{
	if(c2 < 0)
		c2 = wks.GetNumCols()-1;
	
	if(c2 < c1)
		return false;
	
	for(int nCol = c1, ii = 0; nCol <= c2; nCol++, ii++)
	{
		Column col(wks, nCol);
		if(col)
		{
			string strValue = ftoa(dParamValues[ii]);
			vector<string> vsNames, vsValues;
			vsNames.Add(strParamName);
			vsValues.Add(strValue);
			set_user_parameters(col, vsNames, vsValues)	
		}
		else
			return false;
	}
	
	return true;
}

static bool _set_param_values(Worksheet& wks, vector& vParamValues, int nParamType = 0, string& strParamName = NULL, int nParamIndex = 0, int c1 = 0, int c2 = -1)
{
	switch (nParamType)
	{
	case SYSTEM_PARAMETERS:
		if(nParamIndex < 0 || nParamIndex > 9)
			return false;
		
		vector<int> vnIDs;
		wks_get_show_labels(wks, vnIDs);
		vnIDs.Add(nParamIndex+RCLT_PARAM);
		wks_add_show_labels(wks, vnIDs, false);
		return _set_one_sys_parameter_values_wks(wks, vParamValues, nParamIndex, c1, c2);
	case USER_DEFINED_PARAMETERS:
		if(strParamName.IsEmpty())
			strParamName = "UserDefined";
		
		return _set_one_user_defined_parameter_wks(wks, strParamName, vParamValues, c1, c2);
	default:
		return false;
	}
	
	return false;
}

void m2w(const MatrixObject& im, const int& method, const int& xy, const int& ycol, const int& xcol, const int& xlabel, const int& ylabel, const int& sysparam, const string& userdef, const int& option, Worksheet& ow)
{
	
	matrixbase& mat = im.GetDataObject();
	
	if (method_direct == method)
	{
		double dxMin, dxMax, dyMin, dyMax;
		im.GetXY(dxMin, dyMin, dxMax, dyMax);
		int nColNum = mat.GetNumCols();
		int nRowNum = mat.GetNumRows();
		int c1 = 0, c2 = nColNum-1, r1 = 0, r2 = nRowNum-1;
		int tempr1 = r1, tempc1 = c1; 
		bool xrow = xlabel == xlabel_row1;
		bool yrow = ylabel == ylabel_row1;
		if(xy==xy_xcol)
		{	
			DataRange drX, drY;
			vector vx, vy;
			if(xrow)
			{
				r1++; r2++;
				vx.Data(dxMin, dxMax, (dxMax-dxMin)/(nColNum-1));
			}
			
			if(ycol)
			{
				c1++; c2++;
				vy.Data(dyMin, dyMax, (dyMax-dyMin)/(nRowNum-1));	
			}
			ow.SetSize(r2+1, c2+1);
			if(vx.GetSize() > 0)
			{
				drX.Add("X", ow, tempr1, c1, tempr1, c2);
				drX.SetData(vx); 
			}
			
			if(vy.GetSize() > 0)
			{
				drY.Add("X", ow, r1, tempc1, r2, tempc1); 
				Column col(ow, tempc1);
				if(col)
					col.SetType(OKDATAOBJ_DESIGNATION_Y); 
					
				drY.SetData(vy); 
			}
			
			if(!xrow)
			{
				vector vData;
				vData.Data(dxMin, dxMax, (dxMax-dxMin)/(nColNum-1));
				string strParamName = userdef;
				if(xlabel == USER_DEFINED_PARAMETERS && userdef.IsEmpty())
				{
					XF_WARN(1);
					strParamName = "UserDefined";
				}
				_set_param_values(ow, vData, xlabel, strParamName, sysparam, c1, c2);
			}
			
			mat.CopyTo(ow, 0, 0, -1, -1, r1, c1, false, false);
		}
		else if(xy==xy_ycol)
		{
			DataRange drX, drY;
			vector vx, vy;
			
			if(yrow)
			{
				c1++; c2++;
				vy.Data(dyMin, dyMax, (dyMax-dyMin)/(nRowNum-1));
			}
			
			if(xcol)
			{
				r1++; r2++;
				vx.Data(dxMin, dxMax, (dxMax-dxMin)/(nColNum-1));
			}
			ow.SetSize(c2+1, r2+1);
			if(vx.GetSize() > 0)
			{
				drX.Add("X", ow, c1, tempr1, c2, tempr1);
				Column col(ow, tempr1);
				if(col)
					col.SetType(OKDATAOBJ_DESIGNATION_X); 
					
				drX.SetData(vx); 
			}
			
			if(vy.GetSize() > 0)
			{
				drY.Add("X", ow, tempc1, r1, tempc1, r2);
				drY.SetData(vy);
			}
			
			if(!yrow)
			{	
				vector vData;
				vData.Data(dyMin, dyMax, (dyMax-dyMin)/(nRowNum-1));
				string strParamName = userdef;
				if(ylabel == USER_DEFINED_PARAMETERS && userdef.IsEmpty())
				{
					XF_WARN(1);
					strParamName = "UserDefined";
				}
				_set_param_values(ow, vData, ylabel, strParamName, sysparam, r1, r2);
			}
		
			mat.CopyTo(ow, 0, 0, -1, -1, c1, r1, true, false);
		}
		else
		{
			mat.CopyTo(ow, 0, 0, -1, -1, 0, 0, false, false);
		}
		
	}
	else if (method_xyz == method)
	{
		int nRows, nCols;
		
		nRows = im.GetNumRows();
		nCols = im.GetNumCols();
		
		double dXMin, dYMin, dXMax, dYMax;
		im.GetXY(dXMin, dYMin, dXMax, dYMax);
		
		ow.SetSize(-1, 3);
		ow.SetColDesignations("XYZ");
		Dataset dsX(ow, 0), dsY(ow, 1), dsZ(ow, 2);
		
		vector vX(nRows*nCols), vY(nRows*nCols);
		int nRet = ocmath_mat_to_regular_xyz(NULL, nRows, nCols, dXMin, dXMax, dYMin, dYMax, vX, vY, NULL, option);
	
		dsX = vX;
		dsY = vY;
		mat.GetAsVector(dsZ, option);
	}
	else 
	{
		XF_THROW(INTOPTN_OUT_OF_RANGE);
	}
	
	/*
	WorksheetPage wp = ow.GetPage();
	if (wp)
	{
		MatrixLayer ml;
		im.GetParent(ml);
		if (ml)
		{
			MatrixPage mp = ml.GetPage();
			string strLabel = mp.GetName();
			strLabel.Insert(0, ' ');
			strLabel.Insert(0, STR_M2W_WKS_LONGNAME_PRE);
			wp.SetLongName(strLabel);
			wp.TitleShow = WIN_TITLE_SHOW_BOTH;
		}
	}
	*/
}

//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 m2w_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return m2w_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	_update_tree_show(trGetN);
	
	return true;

}

int m2w_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 m2w_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{

}
//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 m2w_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
