#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	format_xcol,
	format_ycol,
	format_noxy,
};
enum{
	xlabel_none,
	xlabel_row1,
	xlabel_param,
};
enum{
	ylabel_none,
	ylabel_row1,
	ylabel_param,
};
//put additional include files here

#include <..\Originlab\WksColLabels.h>		///------ Folger 03/25/09 W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION

/*------------------------------------------------------------------------------*
 * Modification Log:															*
 *	Folger 03/25/09 QA80-13385 W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION			*
 *	Kyle 03/30/2009 QA80-13385 W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
 *	Kyle 07/30/2009 QA80-14046 FIX_X_Y_SWAPPED									*
 *	Kyle 10/22/2009 QA80-13756-P2 SUPPORT_KEYWORDS_ACCESS_FROM_LT_SCRIPT_FOR_COLUMN_LABEL_ROWS
 *------------------------------------------------------------------------------*/

//put your own support static functions here

static	void	_swap_value(int& n1, int& n2)
{
	int n = n1;
	n1 = n2;
	n2 = n;
}

static	void	_prepare_output(Worksheet& wksOut)
{
	for ( int ii=wksOut.GetNumCols()-1; ii>=0; --ii )
	{
		wksOut.DeleteCol(ii);
	}
	
	vector<int>		vnTypes = {OKDATAOBJ_DESIGNATION_X, OKDATAOBJ_DESIGNATION_Y, OKDATAOBJ_DESIGNATION_Z};
	for ( ii=0; ii<vnTypes.GetSize(); ++ii )
	{
		Column	col(wksOut, wksOut.AddCol());
		col.SetType(vnTypes[ii]);
	}
}

///Kyle 03/30/2009 QA80-13385 W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
///Kyle 10/22/2009 QA80-13756-P2 SUPPORT_KEYWORDS_ACCESS_FROM_LT_SCRIPT_FOR_COLUMN_LABEL_ROWS
//static int _get_selected_label_type(const Worksheet& wks, LPCSTR lpcszParam)
static int _get_selected_label_type(const Worksheet& wks, LPCSTR lpcszParam, string* pstrLabel = NULL)
///End SUPPORT_KEYWORDS_ACCESS_FROM_LT_SCRIPT_FOR_COLUMN_LABEL_ROWS
{
	int		nLabelType = RCLT_INVALID;
	///Kyle 10/22/2009 QA80-13756-P2 SUPPORT_KEYWORDS_ACCESS_FROM_LT_SCRIPT_FOR_COLUMN_LABEL_ROWS
	if(pstrLabel)
		pstrLabel->Empty();
	///End SUPPORT_KEYWORDS_ACCESS_FROM_LT_SCRIPT_FOR_COLUMN_LABEL_ROWS

	Column	col(wks, 0);
	vector<string>	vsNames;
	vector<int>		vnTypes;
	get_all_shown_parameters_names_and_values(col, &vsNames, NULL, &vnTypes);
	int nIndex = vsNames.Find(lpcszParam);
	///Kyle 10/22/2009 QA80-13756-P2 SUPPORT_KEYWORDS_ACCESS_FROM_LT_SCRIPT_FOR_COLUMN_LABEL_ROWS
	//if ( nIndex >= 0 )
	//	nLabelType = vnTypes[nIndex];
	if ( nIndex >= 0 )
	{
		nLabelType = vnTypes[nIndex];
		*pstrLabel = vsNames[nIndex];
	}
	else
	{
		vector<int> vnIndices;
		if( okutil_convert_labels_string_to_indices(lpcszParam, &vnIndices) && vnIndices.GetSize() > 0 )
		{
			int nFirstType = vnIndices[0];
			vector<uint> vec;
			if( nFirstType != RCLT_INVALID && vnTypes.Find(vec, nFirstType)>0 )
			{
				nLabelType = nFirstType;
				*pstrLabel = vsNames[vec[0]];
			}
		}
	}
	///End SUPPORT_KEYWORDS_ACCESS_FROM_LT_SCRIPT_FOR_COLUMN_LABEL_ROWS
	
	return nLabelType;
}

static void _set_output_labels(XYZRange& oz, const Worksheet& wksIn, int nDataFormat , int nXValues, int nYValues, string strParam, bool bXFirstCol, bool bYFirstCol)
{
	if(nDataFormat == format_noxy)
		return;
	///Kyle 10/22/2009 QA80-13756-P2 SUPPORT_KEYWORDS_ACCESS_FROM_LT_SCRIPT_FOR_COLUMN_LABEL_ROWS
	//int nLabelType = _get_selected_label_type(wksIn, strParam);
	int nLabelType = _get_selected_label_type(wksIn, strParam, &strParam);
	///End SUPPORT_KEYWORDS_ACCESS_FROM_LT_SCRIPT_FOR_COLUMN_LABEL_ROWS
	if( nLabelType == RCLT_INVALID )		// no need to set it
		strParam.Empty();
	
	Worksheet wks;
	int r1, r2, c1, c2;
	oz.GetRange("X", r1, c1, r2, c2, wks);
	Column colX(wks, c1);
	
	oz.GetRange("Y", r1, c1, r2, c2, wks);
	Column colY(wks, c1);
	
	oz.GetRange("Z", r1, c1, r2, c2, wks);
	Column colZ(wks, c1);
	
	string strXLN, strYLN, strXUnits, strYUnits;
	if(nDataFormat == format_xcol)
	{
		if(nXValues == xlabel_param)
			strXLN = strParam;
		if(bYFirstCol)
		{
			Column col1(wksIn, 0);
			if(col1)
			{
				strYUnits = col1.GetUnits();
				strYLN = col1.GetLongName();
			}
		}
	}
	else
	{
		if(nYValues == ylabel_param)
			strYLN = strParam;
		if(bXFirstCol)
		{
			Column col1(wksIn, 0);
			if(col1)
			{
				strXUnits = col1.GetUnits();
				strXLN = col1.GetLongName();
			}
		}
	}
	if(colX)
	{
		if(!strXLN.IsEmpty())
			colX.SetLongName(strXLN);
		if(!strXUnits.IsEmpty())
			colX.SetUnits(strXUnits);
	}
	if(colY)
	{
		if(!strYLN.IsEmpty())
			colY.SetLongName(strYLN);
		if(!strYUnits.IsEmpty())
			colY.SetUnits(strYUnits);
	}
	
	string strSheetName;
	if(colZ && wksIn.GetName(strSheetName))
	{
		string strLabel;
		strLabel.Format(_L("Z of %s"), strSheetName);
		colZ.SetComments( strLabel );
	}
}
///End W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME

static	double	_prepare_sub_vector(vector& vv, int nSize)
{
	if ( 0 == nSize )
		return NANUM;
	
	if ( vv.GetSize() < nSize )
	{
		vector	vvTmp(nSize - vv.GetSize() + 1);
		vvTmp = NANUM;
		vv.Append(vvTmp);
	}
	
	double	rValue = vv[0];
	vv.RemoveAt(0);
	return rValue;
}

static	double	_get_wks_column_upper_bound(const Worksheet& wks)
{
	int nC = wks.FindFirstEmpty();
	if ( nC < 0 )
		nC = wks.GetNumCols() - 1;
	///Kyle 03/30/2009 QA80-13385 W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
	else
		nC--;
	///End W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
	return nC;
}

static	bool	_has_text_format_column(const Worksheet& wks)
{
	for ( int ii=0; ii<wks.GetNumCols(); ++ ii )
	{
		Column col(wks, ii);
		if ( col.GetFormat() == OKCOLTYPE_TEXT )
			return true;
	}
}

///------ Folger 03/25/09 QA80-13385 W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION
static	void	_update_xy_convert_option_shown(TreeNode& trGetN)
{
	trGetN.xlabel.Show = trGetN.ycol.Show = format_xcol == trGetN.format.nVal;
	trGetN.ylabel.Show = trGetN.xcol.Show = format_ycol == trGetN.format.nVal;
}

static	void	_update_param_option_shown(TreeNode& trGetN)
{
	trGetN.param.Show = ((format_xcol == trGetN.format.nVal && xlabel_param == trGetN.xlabel.nVal) || (format_ycol == trGetN.format.nVal && ylabel_param == trGetN.ylabel.nVal));
}

#define		STR_COMBO_ENDDING		"|"

static	void	_update_param_combo_string(TreeNode& trGetN, const Worksheet& wks)
{
	string		strCombo;
	string		strDefault;
	
	Column col(wks, 0);
	if ( col )
	{
		vector<string>		vsNames;
		if ( get_all_shown_parameters_names_and_values(col, &vsNames, NULL) > 0 )
		{
			strCombo.SetTokens(vsNames, '|');
			strDefault = vsNames[0];
		}			
	}
	
	trGetN.param.SetAttribute(STR_COMBO_ATTRIB, strCombo + STR_COMBO_ENDDING);
	trGetN.param.strVal = strDefault;
}

static	bool	_get_param_row_values(vector<string>& vsValues, Worksheet& wks, int nC1, int nC2, LPCSTR lpcszParam)
{
	///Kyle 03/30/2009 QA80-13385 W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
	//int		nLabelType = -1;
	int nLabelType = _get_selected_label_type(wks, lpcszParam);
	if(nLabelType == RCLT_INVALID)
	{
		vsValues.SetSize(0);
		return false;
	}
	///End W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
	
	vsValues.SetSize(nC2 - nC1 + 1);
	for ( int ii=nC1; ii<=nC2; ++ii )
	{
		Column	col(wks, ii);
		///Kyle 03/30/2009 QA80-13385 W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
		//if ( nLabelType < 0 )
		//{
			//vector<string>	vsNames;
			//vector<int>		vnTypes;
			//get_all_shown_parameters_names_and_values(col, &vsNames, NULL, &vnTypes);
			//int		nIndex = vsNames.Find(lpcszParam);
			//if ( nIndex < 0 )
			//{
				//vsValues.SetSize(0);
				//return false;
			//}
			//
			//nLabelType = vnTypes[nIndex];
		//}
		///End W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
		col.GetExtendedLabel(vsValues[ii], nLabelType);
	}
	
	return true;
}

enum
{
	label_none = xlabel_none,
	label_row1 = xlabel_row1,
	label_param = xlabel_param,
};
///------ End W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION


void w2xyz(const Worksheet& iw, const int& format, const int& xlabel, const int& ylabel, const string& param, const int& xcol, const int& ycol, XYZRange& oz)
{
	if ( _has_text_format_column(iw) )
	{
		XF_THROW(XFERR_TEXT_TYPE_NOT_SUPPORTED_IN_XYZ_CONV)
	}
	
	int			nC1 = 0,  nC2= _get_wks_column_upper_bound(iw);
	int			nR1, nR2;
	iw.GetBounds(nR1, 0, nR2, -1);
	
	if ( nC2 < 0 || nR2 < 0 )
		return;
	
	///------ Folger 03/25/09 QA80-13385 W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION
	bool	bYCrossCol = format_xcol != format;
	
	vector<string>		vsRow;
	vector				vCol;
	
	switch ( format )
	{
	case format_xcol:
	case format_ycol:
		{
			ASSERT(xlabel_none == ylabel_none && xlabel_row1 == ylabel_row1 && xlabel_param == ylabel_param);
			int		label = format_xcol == format ? xlabel : ylabel;
			int		col = format_xcol == format ? ycol : xcol;
			
			if ( col )
			{
				switch ( label )
				{
				case label_none:
					{
						vector<int>		vnData;
						vnData.Data(0, nC2 - nC1);
						convert_int_vector_to_string_vector(vnData, vsRow);
					}
					break;
					
				case label_param:
					_get_param_row_values(vsRow, iw, nC1, nC2, param);
					break;
					
				case label_row1:
				default:
					break;
				}
			}
			else
			{
				vCol.Data(0, nR2 - nR1 + 1);
				
				switch ( label )
				{
				case label_none:
					{
						vector<int>		vnData;
						vnData.Data(0, nC2 - nC1 + 1);
						convert_int_vector_to_string_vector(vnData, vsRow);
					}
					break;
					
				case label_param:
					_get_param_row_values(vsRow, iw, nC1, nC2, param);
					vsRow.InsertAt(0, "");
					break;
					
				case label_row1:
					vCol.SetSize(nR2 - nR1 + 1);
					
					break;
				default:
					break;
				}
			}
		}		
		break;
		
	case format_noxy:
		{
			vector<int>		vnData;
			vnData.Data(0, nC2 - nC1 + 1);
			convert_int_vector_to_string_vector(vnData, vsRow);
			
			vCol.Data(0, nR2 - nR1 + 1);
		}
		break;
		
	default:
		break;
	}
	///------ End W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION
	
	Worksheet wks;
	wks.CreateCopy(iw, CREATE_HIDDEN, DCTRL_COPY_DATA);
	
	///------ Folger 03/25/09 QA80-13385 W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION
	if ( vCol.GetSize() > 0 )
	{
		string		strTmp;
		wks.InsertCol(nC1, "", strTmp);
		++nC2;
	}
	if ( vsRow.GetSize() > 0 )
	{
		wks.InsertRow(nR1);
		++nR2;
	}
	
	if ( vCol.GetSize() > 0 )
	{
		vectorbase&	vv = wks.Columns(nC1).GetDataObject();
		if ( nR1 > 0 )
			vCol.InsertAt(0, NANUM, nR1);
		vv = vCol;
	}
	if ( vsRow.GetSize() > 0 )
	{
		wks.SetCells(vsRow, nR1, nC1);
	}
	///------ End  W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION
	
	if ( nC2 - nC1 > nR2 - nR1 )
	{
		wks.Transpose();
		_swap_value(nC1, nR1);
		_swap_value(nC2, nR2);
		bYCrossCol = !bYCrossCol;				///Kyle 07/30/2009 QA80-14046 FIX_X_Y_SWAPPED
	}
	
	//_prepare_output(ow);
	_set_output_labels(oz, iw, format, xlabel, ylabel, param, xcol, ycol);///Kyle 03/30/2009 QA80-13385 W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
	
	vector		vXPart;
	vXPart = wks.Columns(nC1).GetDataObject();
	vXPart.GetSubVector(vXPart, nR1);		///------ Folger 03/25/09 QA80-13385 W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION
	_prepare_sub_vector(vXPart, nR2 - nR1 + 1);
	
	///Kyle 03/30/2009 QA80-13385 W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
	//vectorbase&	vX = ow.Columns(0).GetDataObject();
	//vectorbase&	vY = ow.Columns(1).GetDataObject();
	//vectorbase&	vZ = ow.Columns(2).GetDataObject();
	vector vX, vY, vZ;
	///End W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
	
	for (++nC1; nC1<=nC2; ++nC1 )
	{
		vector	vYPart, vZPart;
		
		vZPart = wks.Columns(nC1).GetDataObject();
		vZPart.GetSubVector(vZPart, nR1);		///------ Folger 03/25/09 QA80-13385 W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION
		double	rValue = _prepare_sub_vector(vZPart, vXPart.GetSize());
				
		vYPart.SetSize(vZPart.GetSize());
		vYPart = rValue;
		
		if ( bYCrossCol )
		{
			vX.Append(vXPart);
			vY.Append(vYPart);
		}
		else
		{
			vX.Append(vYPart);
			vY.Append(vXPart);
		}
		vZ.Append(vZPart);
	}
	oz.SetData(&vZ, &vY, &vX);			///Kyle 03/30/2009 QA80-13385 W2XYZ_CARRY_OVER_LABELS_AS_LONGNAME
	
	wks.Destroy();
	
}

//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 w2xyz_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return w2xyz_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	///------ Folger 03/25/09 QA80-13385 W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION
	Worksheet	wks;
	okxf_resolve_string_get_origin_object(trGetN.iw.strVal, &wks);
	
	if ( GETNE_ON_INIT == nEventID || GETNE_ON_THEME == nEventID )
	{
		_update_xy_convert_option_shown(trGetN);
		_update_param_option_shown(trGetN);
		_update_param_combo_string(trGetN, wks);
	}
	else if ( 0 == lstrcmpi(lpcszNodeName, "format") )
	{
		_update_xy_convert_option_shown(trGetN);
		_update_param_option_shown(trGetN);
	}
	else if ( 0 == lstrcmpi(lpcszNodeName, "iw") )
	{
		_update_param_combo_string(trGetN, wks);
	}
	else if ( 0 == lstrcmpi(lpcszNodeName, "xlabel") || 0 == lstrcmpi(lpcszNodeName, "ylabel") )
	{
		_update_param_option_shown(trGetN);
	}
	
	string		strCombo;	
	if ( !wks )
	{
		trGetN.param.Enable = DISABLE;
		bOKEnable = false;
		strErrMsg = CER_NO_WORKSHEET;
	}
	else if ( ((format_xcol == trGetN.format.nVal && xlabel_param == trGetN.xlabel.nVal) || (format_ycol == trGetN.format.nVal && ylabel_param == trGetN.ylabel.nVal)) &&
		!trGetN.param.GetAttribute(STR_COMBO_ATTRIB, strCombo) || strCombo == STR_COMBO_ENDDING )
	{
		trGetN.param.Enable = DISABLE;
		bOKEnable = false;
		strErrMsg = XFERR_WORKSHEET_HAS_NO_SHOW_PARAMS;
	}
	else
	{
		trGetN.param.Enable = ENABLE;
	}
	
	return true;
	///------ End W2XYZ_SUPPORT_MORE_OPTIONS_ON_CONVERSION

}

int w2xyz_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 w2xyz_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	Worksheet	wks;
	if ( 0 == nGetNDialog && !okxf_resolve_string_get_origin_object(trGetN.iw.strVal, &wks) )
	{
		warning_msg_box(CER_NO_WORKSHEET, true);
		nRet = XFEVT_ABORT;
		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 w2xyz_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
