#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
//put additional include files here

/**********************************************************************************
	Modification Log :

	Folger 08/01/08 SHOULD_USE_UPPERBOUND_INSTEAD_OF_ROWS_NUMBER_FOR_SHOW_EVEN_SAMPLING
	RVD 8/4/2008 qa70-11943 SAMPLING_BETETR_COL_X
	Folger 08/13/08 IMPROVE_ERROR_CHECKING_ON_Y_COLUMN_AND_EVEN_SAMPLING
	Folger 09/23/08 QA80-12255 SET_NEW_COLUMN_TYPE_TO_X_FOR_Y_SOURCE_COLUMN
**********************************************************************************/

//put your own support static functions here
/*
static bool _is_same(string& str1, string& str2)
{
	return str1.Compare(str2) == 0 ? true : false;
}

static bool _is_same(double x1, double x2)
{
	string strX1, strX2; 
	strX1 = ftoa(x1); 
	strX2 = ftoa(x2);
	return _is_same(strX1, strX2);
}

static bool _is_need_and_x_col(Worksheet& wks, int nYCol, double& x0, double& xInc, string& strXUnits, string& strXLongName)
{
	Column col(wks, nYCol);
	if(!col.IsValid())
		return false;
	
	double curX0, curXInc;
	string strCurXUnits = NULL, strCurXLongName = NULL;
	if(!col.IsEvenSampling(&curX0, &curXInc, strCurXUnits, strCurXLongName))
	{
		curX0 = 1;
		curXInc = 1;
		strCurXLongName = col.GetLongName();
		strCurXUnits = col.GetUnits();
	}
		
	bool bSameLName, bSameUnits, bSameX0, bSameXInc;
	bSameLName = _is_same(strCurXUnits, strXUnits);
	bSameUnits = _is_same(strCurXLongName, strXLongName);
	bSameX0 = _is_same(curX0, x0);
	bSameXInc = _is_same(curXInc, xInc);
	bool bPreIsX = false;
	if(nYCol > 0)
	{
		Column col1(wks, nYCol-1);
		if(col1)
		{
			if(col1.GetType() == OKDATAOBJ_DESIGNATION_X)
				bPreIsX = true;
		}
	}
	
	x0 = curX0; xInc = curXInc;	
	strXUnits = strCurXUnits;
	strXLongName = strCurXLongName;
	if(nYCol == 0 ||( (!bSameX0 || !bSameXInc || !bSameLName || !bSameUnits) && !bPreIsX ))
		return true;
	
	return false;
}

static void _show_x_column(Worksheet &wks) 
{
	int nColNum = wks.GetNumCols();
	int nPreYCol = -1, ii = 0;
	double x0 = 1, xInc = 1;
	string strXUnits = NULL, strXLongName = NULL;
	DWORD dwCntrl = FCI_RIGHT;
	int nYCol;
	Column col(wks, 0);
	if(col)
	{
		if(col.GetType() == OKDATAOBJ_DESIGNATION_Y)
			nYCol = 0;
		else
			nYCol = wks.FindColIndex(0, OKDATAOBJ_DESIGNATION_Y, dwCntrl);
	}
	
	while(nYCol>=0 && nYCol < nColNum)
	{	
		/*
		Column col(wks, nYCol);
		double x0, xInc;
		string strXUnits = NULL, strXLongName = NULL;
		if(!col.IsEvenSampling(&x0, &xInc, strXUnits, strXLongName))
		{
			x0 = x0Pre;
			xInc = xIncPre;
			strXLongName = col.GetLongName();
			strXUnits = col.GetUnits();
		}
		
		bool bSameLName, bSameUnits, bSameX0, bSameXInc;
		bSameLName = _is_same(strXUnits, strPreXUnits);
		bSameUnits = _is_same(strXLongName, strPreXLongName);
		bSameX0 = _is_same(x0, x0Pre);
		bSameXInc = _is_same(xInc, xIncPre);
		int nRows = col.GetNumRows();
		vector vx(nRows);
		if(nYCol == 0 || nYCol != nPreYCol+1 || !bSameX0 || !bSameXInc || !bSameLName || !bSameUnits)
		{
		*/
		/*
		if(_is_need_and_x_col(wks, nYCol, x0, xInc, strXUnits, strXLongName))
		{
			Column col(wks, nYCol);
			col.SetEvenSampling(1, 1);
			int nRows = col.GetNumRows();
			vector vx;
			vx.Data(x0, x0+xInc*(nRows-1), xInc);
			string strName = "X" + ftoa(ii);
			wks.InsertCol(nYCol, NULL, strName);
			Column xCol(wks, nYCol);
			if(xCol)
			{
				xCol.SetType(OKDATAOBJ_DESIGNATION_X); 
				xCol.SetLongName(strXLongName);
				xCol.SetUnits(strXUnits);
				vectorbase& vec = xCol.GetDataObject();
				vec = vx;
			}
			//x0Pre = x0; xIncPre = xInc;	
			//strPreXUnits = strXUnits;
			//strPreXLongName = strXLongName;
			nYCol++;
			nColNum++;
			ii++;
		}
		
		nPreYCol = nYCol;
		nYCol = wks.FindColIndex( nPreYCol, OKDATAOBJ_DESIGNATION_Y, dwCntrl);
	}
}
*/

static void _get_sorted_columns_from_range(const DataRange& dr, Worksheet& wks, vector& vc1, vector& vc2)
{
	int r1, r2, c1, c2;
	int nNum = dr.GetNumRanges();
	
	for(int ii = 0; ii < nNum; ii++)
	{
		dr.GetRange(ii, r1, c1, r2, c2, wks);
		vc1.Add(c1);
		vc2.Add(c2);
	}
	vector<uint> vnIndeces;
	vc2.Sort(SORT_ASCENDING, TRUE, vnIndeces);
	vc1.Reorder(vnIndeces);	
}

//------ Folger 08/13/08 IMPROVE_ERROR_CHECKING_ON_Y_COLUMN_AND_EVEN_SAMPLING
//static bool _show_x_column(DataRange& dr, const int& clear)
static bool _show_x_column(DataRange& dr, const int& clear, bool bCheckOnly = false, bool *pbHasY = NULL)
//------
{
	//------ Folger 01/18/08 QA70-10946 SUPPORT_MULTIPLE_SHEETS_OPERATION_WITH_SHEET_RANGE_LIST_CLASS
	SheetRangesList rngList(dr);
	int nNumSheet = rngList.GetNumSheets();
	
	for ( int ii=0; ii<nNumSheet; ++ii )
	{
		DataRange drSub;
		if ( rngList.GetWksSubRange(ii, drSub) )
		{
	//------
			vector vc1, vc2;
			Worksheet wks;
			//------ Folger 01/18/08 QA70-10946 SUPPORT_MULTIPLE_SHEETS_OPERATION_WITH_SHEET_RANGE_LIST_CLASS
			//_get_sorted_columns_from_range(dr, wks, vc1, vc2);
			_get_sorted_columns_from_range(drSub, wks, vc1, vc2);
			//------
			int nSize = vc1.GetSize();
			int nShowX = 0;
			bool bUndo = true;	/// RVD 7/30/2008 qa70-11914 SAMPLE_INTERVAL_UNDO
			
			int nAddedForWks = 0; //---- CPY RVD 8/4/2008 qa70-11943 SAMPLING_BETETR_COL_X
			
			for(int ii = 0; ii < nSize; ii++)
			{				
				for(int jj = vc1[ii]; jj <= vc2[ii]; jj++)
				{
					Column col(wks, jj+nShowX);
					//------ Folger 09/23/08 QA80-12255 SET_NEW_COLUMN_TYPE_TO_X_FOR_Y_SOURCE_COLUMN
					//if(col && col.GetType() == OKDATAOBJ_DESIGNATION_Y)
					if(col && (col.GetType() == OKDATAOBJ_DESIGNATION_Y || col.GetType() == OKDATAOBJ_DESIGNATION_X) )
					//------
					{
						//------ Folger 08/13/08 IMPROVE_ERROR_CHECKING_ON_Y_COLUMN_AND_EVEN_SAMPLING
						if ( pbHasY )
							*pbHasY = true;
						//------						
						int nYCol = jj+nShowX;
						double x0, xInc;
						string strXUnits, strXLongName;
						if(col.IsEvenSampling(&x0, &xInc, strXUnits, strXLongName))
						{
							//------ Folger 08/13/08 IMPROVE_ERROR_CHECKING_ON_Y_COLUMN_AND_EVEN_SAMPLING
							if ( bCheckOnly )
								return true;
							//------
							//------ Folger 08/01/08 SHOULD_USE_UPPERBOUND_INSTEAD_OF_ROWS_NUMBER_FOR_SHOW_EVEN_SAMPLING
							//int nRows = col.GetNumRows();
							int nUpperBound = col.GetUpperBound();
							//------
							vector vx;
							//------ Folger 08/01/08 SHOULD_USE_UPPERBOUND_INSTEAD_OF_ROWS_NUMBER_FOR_SHOW_EVEN_SAMPLING
							//vx.Data(x0, x0+xInc*(nRows-1), xInc);
							/// RVD 8/4/2008 qa70-11943 ZERO_INC_SAMPLING
							// vx.Data(x0, x0+xInc*nUpperBound, xInc);
							if(nUpperBound > 0) // has value
							{
								if( xInc == 0.0 )
								{
									vx.SetSize(nUpperBound + 1);
									vx = x0;
								}
								else
								{
									if( !vx.Data(x0, x0+xInc*nUpperBound, xInc) )
										return false;
								}
							}
							/// end ZERO_INC_SAMPLING
							//------
							string strName = "X" + ftoa(nYCol);
							/// RVD 7/30/2008 qa70-11914 SAMPLE_INTERVAL_UNDO
							//wks.InsertCol(nYCol, NULL, strName);
							wks.InsertCol(nYCol, NULL, strName, bUndo);
							/// end SAMPLE_INTERVAL_UNDO
							Column xCol(wks, nYCol);
							if(xCol)
							{
								///---- CPY RVD 8/4/2008 qa70-11943 SAMPLING_BETETR_COL_X
								//xCol.SetType(OKDATAOBJ_DESIGNATION_X); 
								xCol.SetType(OKDATAOBJ_DESIGNATION_NONE);
								///----
								xCol.SetLongName(strXLongName);
								xCol.SetUnits(strXUnits);
								///---- CPY RVD 8/4/2008 qa70-11943 SAMPLING_BETETR_COL_X
								string strTemp = "Generated from Sampling Info of " + col.GetName();
								xCol.SetComments(strTemp);
								///---- end SAMPLING_BETETR_COL_X
								vectorbase& vec = xCol.GetDataObject();
								vec = vx;
							}
							if(clear)
							{
								/// RVD 7/30/2008 qa70-11914 SAMPLE_INTERVAL_UNDO
								//col.SetEvenSampling(1, 1);
								col.SetEvenSampling(1, 1, NULL, NULL, NULL, bUndo);
								/// end SAMPLE_INTERVAL_UNDO
								//------ Folger 09/23/08 QA80-12255 SET_NEW_COLUMN_TYPE_TO_X_FOR_Y_SOURCE_COLUMN
								if ( col.GetType() == OKDATAOBJ_DESIGNATION_Y && xCol )
									xCol.SetType(OKDATAOBJ_DESIGNATION_X);
								//------
							}
							nShowX++;
							nAddedForWks++; ///---- CPY RVD 8/4/2008 qa70-11943 SAMPLING_BETETR_COL_X
						}
					}
				}
				///---- CPY RVD 8/4/2008 qa70-11943 SAMPLING_BETETR_COL_X
				if(nAddedForWks)
					wks.AutoSizeRow(RCLT_COMMENT, 1);
				///----
			}
	//------ Folger 01/18/08 QA70-10946 SUPPORT_MULTIPLE_SHEETS_OPERATION_WITH_SHEET_RANGE_LIST_CLASS
	//if(nShowX > 0)
		//return true;
	//return false;
			if ( nShowX <= 0 )
				return false;			
		}
	}
	return true;
	//------
}

static int _check_input_error(TreeNode& trGetN)
{
	DataRange dr;
	TreeNode trInput = trGetN.rng;

	int nErr = CER_NO_ERROR;
	
	if(!okxf_resolve_tree_construct_range(&trInput, &dr) || dr.GetNumRanges() <= 0 )
		nErr = XFERR_INVALID_RANGE;

	return nErr;
}


void colshowx(Range& rng, const int& clear)
{
	
	/*
	vector vX0, vXInc;
	vector<uint> vColInd;
	_show_x_column(wks); 	
	wks.SetEvenSampling(1, 1);
	wks.HideLabelByType(TRUE, RCLT_SAMPLE_RATE);
	*/
	if( !rng.IsValid() || rng.GetNumRanges() <= 0 )
		XF_THROW(XFERR_INVALID_RANGE);
		
	if(!_show_x_column(rng, clear))
		XF_THROW(XFERR_NO_X_OR_Y_WITH_SAMPLING_INTERVAL);	
}

//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 colshowx_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return colshowx_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	int nErr = CER_NO_ERROR;
	
	_check_input_error(trGetN);
	
	if((nErr = _check_input_error(trGetN)) != CER_NO_ERROR)
	{
		bOKEnable = false;
		strErrMsg = nErr;
	}
	
	//------ Folger 08/13/08 IMPROVE_ERROR_CHECKING_ON_Y_COLUMN_AND_EVEN_SAMPLING
	bool		bHasY = false;
	TreeNode	trRng = trGetN.rng;
	Range		rng;
	okxf_resolve_tree_construct_range(&trRng, &rng);
	
	bool	bIsEvenSampling = _show_x_column(rng, 0, true, &bHasY);
	
	if ( nErr == CER_NO_ERROR )
	{
		bOKEnable = false;
		if ( !bHasY )
		{
			strErrMsg = XFERR_NO_X_OR_Y_COLUMN;
		}
		else if ( !bIsEvenSampling )
		{
			strErrMsg = XFERR_NO_X_OR_Y_WITH_SAMPLING_INTERVAL;
		}
		else
		{
			bOKEnable = true;
		}
	}
	//------ End IMPROVE_ERROR_CHECKING_ON_Y_COLUMN_AND_EVEN_SAMPLING
	
	return false;

}

int colshowx_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 colshowx_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	if(_check_input_error(trGetN) == CER_NO_ERROR && (dwCntrl&LTXF_FROM_GUI_MENU))
		nRet = XFEVT_PROCEED_NO_DLG;
	else
		nRet = XFEVT_PROCEED;
}
//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 colshowx_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
