/*------------------------------------------------------------------------------*
 * File Name:				 													*
 * Creation: CPY 6/22/05														*
 * Purpose: OriginC Source C file												*
 * Copyright (c) Originlab Corp.	2005, 2006, 2007, 2008, 2009, 2010			*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Jasmine 09/19/06 CHECK_ADD_ROW#												*
 * Jake 04/04/07 SHOW_DATAINFO_FROM_FUNCTION_PLOTS								*
 * Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME						*
 * Folger 08/14/07 #10213 SUPPORT_3D_GRAPH_IN_DATA_INFO_WINDOW					*
 * Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ				*
 *	Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO				*
 *	Folger 07/02/10 ORG-436-P4 DATA_INFO_CURSOR_FAILED_TO_GET_CATEGORICAL_DATA	*
 *	Folger 09/02/2010 ORG-968-P1 RUNTIME_ERROR_IF_IMAGE_PLOT_WITH_COMPLEX_VALUE	*
 *------------------------------------------------------------------------------*/

class DataInfoCursor
{
public:
	DataInfoCursor()
	{
		m_nLastRow = -1;
		m_nPlotSrcType = EXIST_NONE;	//------ Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
		///------ Folger 06/30/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
		m_nLastPlotUID = 0;
		///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
	}
private:
	//------ Folger 08/14/07 #10213 SUPPORT_3D_GRAPH_IN_DATA_INFO_WINDOW
	//bool getWksCol(DataPlot& dp, Column& cc, Worksheet& wks)
	//{
		//string strDataset = dp.GetDatasetName();
		//return get_wks_col(strDataset, cc, wks);
	//}
	bool getDatasheetDataobj(DataPlot& dp, DataObject& dataObj, Datasheet& ds)
	{
		string strDataset = dp.GetDatasetName();
		return get_datasheet_dataobj(strDataset, dataObj, ds);
	}
	//------ End #10213 SUPPORT_3D_GRAPH_IN_DATA_INFO_WINDOW
	bool getAllWksCols(Worksheet& wks, int nRow, vector<string>& vsCol, vector<string>& vsName, vector<string>& vsVal, bool bLongAndShortName = false)
	{
		foreach(Column co in wks.Columns)
		{
			string str = co.GetName();
			//str += _get_col_designation(co.GetType());
			vsCol.Add(str);
			string strName = co.GetLongName();
			//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
			if(bLongAndShortName&&!strName.IsEmpty())
			{
				strName.Insert(0,"-");
				strName.Insert(0,str);
			}
			//end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
			if(strName.IsEmpty())
				strName = str;
			vsName.Add(strName);
			int nCol = co.GetIndex();
			wks.GetCell(nRow, nCol, str);
			vsVal.Add(str);
		}
		return true;
	}	
	bool getPlotCols(Worksheet& wks, DataPlotStrings& dps, vector<string>& vsPlot, vector<string>& vsPlotCol)
	{
		string strBook, strSheet, strPlot, strLongName, strCol;
		for(int ii = COLDESIG_X; ii < COLDESIG_TOTAL_NUM; ii++)
		{
			if(get_plot_info(ii, dps, strBook, strSheet, strPlot, strLongName, strCol))
			{
				vsPlot.Add(strPlot);
				vsPlotCol.Add(strCol);
			}
		}
		return true;
	}
	//------ Folger 08/14/07 #10213 SUPPORT_3D_GRAPH_IN_DATA_INFO_WINDOW
	bool getMatrixInfo(const MatrixObject &mo, int nRow, string strBook, string strSheet, bool bLongAndShortName = false)
	{
		m_vsVal.SetSize(3);
		m_vsVal[2] = _get_matrix_value_by_row(mo, nRow, m_vsVal[0], m_vsVal[1]);
		string strShortName = mo.GetName();
		string strLongName = mo.GetLongName();
		string strShortLongName;
		if (strLongName.IsEmpty())
			strShortLongName = strShortName;
		else
		{
			if (bLongAndShortName)
				strShortLongName = strShortName + '-' + strLongName;
			else
				strShortLongName = strLongName;
		}
		for (int ii=0; ii<3; ii++)
		{
			m_vsBook.Add(strBook);
			m_vsWks.Add(strSheet);
			m_vsName.Add(strShortLongName);
		}
		m_vsPlot.Add("X");
		m_vsPlot.Add("Y");
		m_vsPlot.Add("Z");
		return true;
	}
	//------ End SUPPORT_3D_GRAPH_IN_DATA_INFO_WINDOW
public:
	void Reset(bool bResetLastIndex = true)
	{
		if(bResetLastIndex)
			m_nLastRow = -1;
		
		m_vsCursor.SetSize(0);
		m_vsBook.SetSize(0);
		m_vsWks.SetSize(0);
		m_vsPlot.SetSize(0);
		m_vsName.SetSize(0);
		m_vsVal.SetSize(0);
	}
	bool IsValid()
	{
		return m_vsPlot.GetSize() > 0? true:false;
	}
	bool GetDifferences(DataInfoCursor& ci1, DataInfoCursor& ci2)
	{
		Reset();
		double x1, y1, z1;
		double x2, y2, z2;
		int n1 = ci1.GetLastXYZ(x1, y1, z1);
		int n2 = ci2.GetLastXYZ(x2, y2, z2);
		if(n1 != n2)
			return false;
		string strName = ci2.GetLastName() + " - " + ci1.GetLastName();
		vector<string> vsDiffNames = {"dx", "dy", "dz"};
		for(int ii = 0; ii < n1; ii++)
		{
			m_vsBook.Add("");
			m_vsWks.Add("");
			m_vsCursor.Add(strName);
			m_vsPlot.Add(vsDiffNames[ii]);
			m_vsName.Add("");//strName);
			double dVal;
			switch(ii)
			{
			case 0:
				dVal = x2 - x1;
				///------ Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
				m_x = dVal;
				///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
				break;
			case 1:
				dVal = y2 - y1;
				///------ Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
				m_y = dVal;
				///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
				break;
			case 2:
				dVal = z2 - z1;
				///------ Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
				m_z = dVal;
				///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
				break;
			}
			m_vsVal.Add(ftoa(dVal));
		}
		return true;	
	}
	bool GetPlotWksInfo(int nCursor, int nLayer, int nPlot, int nRow, bool bAllCols = false, bool bLongAndShortName = false)
	{
		Reset();
		GraphPage gp = Project.Pages();
		if(!gp)
			return false;
		
		GraphLayer gl = gp.Layers(nLayer);
		if(!gl)
			return false;
		DataPlot dp = gl.DataPlots(nPlot);
		if(!dp)
			return false;
		///------ Folger 06/30/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
		m_nLastPlotUID = dp.GetUID(TRUE);
		///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
		DataPlotStrings dps;
		int nPlotType = dp.GetPlotType(&dps);
		if(nPlotType > 0)
		{
			string strBook, strSheet, strPlot, strLongName, strVal;
			//------ Folger 08/14/07 #10213 SUPPORT_3D_GRAPH_IN_DATA_INFO_WINDOW
			//Column cc;
			//Worksheet wks;
			//getWksCol(dp, cc, wks);
			////strTemp.Format("%d",nRow + 1);
			//if(wks)
			//{
				//strBook = wks.GetPage().GetName();
				//strSheet = wks.GetName();
			//}
			DataObject dataObj;
			Datasheet ds;
			getDatasheetDataobj(dp, dataObj, ds);
			if (ds)
			{
				strBook = ds.GetPage().GetName();
				strSheet = ds.GetName();
			}
			
			Worksheet wks(ds);
			MatrixLayer ml(ds);
			
			if (ml)
			{
				MatrixObject mo(dataObj);
				getMatrixInfo(mo, nRow, strBook, strSheet, bLongAndShortName);
				m_nPlotSrcType = EXIST_MATRIX;	//------ Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
			}
			//------ Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
			else
			{
				m_nPlotSrcType = EXIST_WKS;
			//------ End CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
			
			//------ End SUPPORT_3D_GRAPH_IN_DATA_INFO_WINDOW
			//Add(strTemp, strBook, strSheet, "Row #");
			
			///Jasmine 09/19/06 CHECK_ADD_ROW#
			//if there'so X column and dataplot uses "offset and scale"
			//get dwAuxTypeInfo
			//if( !(dwAuxTypeInfo & PCD_NO_X) && !(dwAuxTypeInfo & PCD_ONLY_ONE_Z) )			
			if(!lstrlen(get_plot_dataset_ptr(&dps, COLDESIG_X)))//temp
			{
                char szTemp[NAME_SIZE];
				
                if(wks)//if get value from wks with only Y plots
				{
					if(get_plot_designation_str(COLDESIG_X, szTemp, NAME_SIZE))
						strPlot = szTemp;	
			    //get value X from step
					double dbFrom, dbStep;
					string strDataset = dp.GetDatasetName();
					GetDatasetXFromStep(strDataset, &dbFrom, &dbStep);
					strVal = (string)(dbFrom + nRow * dbStep);
					m_vsBook.Add(strBook);
					m_vsWks.Add(strSheet);
					m_vsPlot.Add(strPlot);
					m_vsName.Add("From/Step=");//long name, ROW#:column name
					m_vsVal.Add(strVal);
				}
				//Jake 03/04/07 SHOW_DATAINFO_FROM_FUNCTION_PLOTS
				else//if get value from function plots
				{
	    			double X, Y;
		    		BOOL bRet = dp.GetDataPoint(nRow, &X, &Y);
		    		if(get_plot_designation_str(COLDESIG_X, szTemp, NAME_SIZE))
		     			strPlot = szTemp;	
					string strX(X);
					strVal=strX;
					m_vsBook.Add(strBook);
					m_vsWks.Add(strSheet);
					m_vsPlot.Add(strPlot);
			    	m_vsName.Add("X");
					m_vsVal.Add(strVal);
				

				//to add the Y value 
					if(get_plot_designation_str(COLDESIG_Y, szTemp, NAME_SIZE))
						strPlot = szTemp;
			    	string strY(Y);
		    		strVal=strY;
			    	m_vsBook.Add(strBook);
		    		m_vsWks.Add(strSheet);
			    	m_vsPlot.Add(strPlot);
		        	m_vsName.Add(dps.szY);
			    	m_vsVal.Add(strVal);
				}
				
			}
			///End CHECK_ADD_ROW#
			if(bAllCols)
			{
				vector<string> vsName, vsVal, vsPlot, vsCol, vsPlotCol;
				getAllWksCols(wks, nRow, vsCol, vsName, vsVal, bLongAndShortName);
				getPlotCols(wks, dps, vsPlot, vsPlotCol);
				int nn;
				for(int ii = 0; ii < vsCol.GetSize(); ii++)
				{
					m_vsBook.Add(strBook);
					m_vsWks.Add(strSheet);
					if(is_in_list(vsCol[ii], vsPlotCol, false, &nn))
						m_vsPlot.Add(vsPlot[nn]);
					else
						m_vsPlot.Add("");
				}
				m_vsName.Append(vsName);
				m_vsVal.Append(vsVal);
			}
			else
			{
		    	//if the data from workbook
		    	if(wks)
					for(int ii = COLDESIG_X; ii < COLDESIG_TOTAL_NUM; ii++)
					{
						//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
						bool bRealLongName = false;
						string strShortName;
						if(get_plot_info(ii, dps, strBook, strSheet, strPlot, strLongName, strShortName, nRow, strVal, bRealLongName))
						{
							m_vsBook.Add(strBook);
							m_vsWks.Add(strSheet);
							m_vsPlot.Add(strPlot);
							if(bLongAndShortName)
							{
								string strLongAndShortName;
								strLongAndShortName += strShortName;
								if(bRealLongName)
								{
									strLongAndShortName += "-";
									strLongAndShortName += strLongName;
								}
								m_vsName.Add(strLongAndShortName);
							}
							else
								m_vsName.Add(strLongName);
							//----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
							m_vsVal.Add(strVal);
							
						}
					}
			}
			
			} //if (ml)		//------ Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
			
			///------ Folger 07/02/10 ORG-436-P4 DATA_INFO_CURSOR_FAILED_TO_GET_CATEGORICAL_DATA
			//m_nXYZ = get_xyz_values(dps, nRow, m_x, m_y, m_z);
			m_nXYZ = get_xyz_values(dp, nRow, m_x, m_y, m_z);
			///------ End DATA_INFO_CURSOR_FAILED_TO_GET_CATEGORICAL_DATA
			m_nLastRow = nRow;
			m_nLastCursor = nCursor;
			m_nLastLayer = nLayer;
			m_nLastPlot = nPlot;
		}
		m_strName = "DR";
		if(nCursor >= 0)
			m_strName = (string) "C" + (1+nCursor);
		
		m_strName += (string)" [" + (nRow + 1) + "]";
		int nSize = m_vsVal.GetSize();
		m_vsCursor.SetSize(nSize);
		for(int ii = 0; ii < nSize; ii++)
			m_vsCursor[ii] = m_strName;
		return true;
	}	
	//----Jake 04/06/07 ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
	//add bLongAndShortName as a bool value 
	bool UpdateUsingLastIndex(bool bAllCols, bool bLongAndShortName)
	{
		if(m_nLastRow>=0)
		{
			Reset(false);
			return GetPlotWksInfo(m_nLastCursor, m_nLastLayer, m_nLastPlot, m_nLastRow, bAllCols, bLongAndShortName);
		}
		return false;
	}
	//----end ADD_CHECKBOX_FOR_SHOW_LONG_AND_SHORT_NAME
	void Add(LPCSTR lpcszVal, LPCSTR lpcszBook = NULL, LPCSTR lpcszWks = NULL, LPCSTR lpcszCol = NULL, LPCSTR lpcszName = NULL)
	{
		string str = lpcszVal;
		m_vsVal.Add(str);
		str = lpcszBook;
		m_vsBook.Add(str);
		str = lpcszWks;
		m_vsWks.Add(str);
		str = lpcszCol;
		m_vsPlot.Add(str);
		str = lpcszName;
		m_vsName.Add(str);
	}
		
	int Append(vector<string>& vsCursor, vector<string>& vsBooks, vector<string>& vsWks, vector<string>& vsPlot, vector<string>& vsName, vector<string>& vsVal)
	{
		if(vsPlot.GetSize() > 0) // add separator
		{
			vsCursor.Add(""); vsBooks.Add("");vsWks.Add("");
			vsPlot.Add("");vsName.Add("");vsVal.Add("");
		}
		vsCursor.Append(m_vsCursor);
		vsBooks.Append(m_vsBook);
		vsWks.Append(m_vsWks);
		vsPlot.Append(m_vsPlot);
		vsName.Append(m_vsName);
		vsVal.Append(m_vsVal);
		return 1;
	}
	int	GetLastXYZ(double& x, double& y, double& z) {x = m_x, y = m_y, z = m_z; return m_nXYZ;}
	string GetLastName()
	{
		string str = m_strName;
		int nPos = str.Find('[');
		if(nPos > 0)
		{
			str = m_strName.Left(nPos);
			str.TrimRight();
		}
		return str;
	}
	//------ Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
	int GetPlotSrcType()
	{
		return m_nPlotSrcType;
	}
	//------ End CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ

	///------ Folger 06/30/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
	int		GetLastPlotUID(int* pnIndex)
	{
		if ( pnIndex )
			*pnIndex = m_nLastRow;

		return m_nLastPlotUID;
	}
	///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO

private:
	int		m_nLastRow;
	int		m_nLastCursor, m_nLastLayer, m_nLastPlot;
	string	m_strName;
	double 	m_x, m_y, m_z;
	int 	m_nXYZ;
	vector<string> m_vsCursor, m_vsBook, m_vsWks, m_vsPlot, m_vsName, m_vsVal;
	int		m_nPlotSrcType;		//------ Folger 08/15/07 CORRECT_CONTROL_DISPLAY_FOR_BOTH_COLUMN_MATOBJ
	///------ Folger 06/30/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
	int		m_nLastPlotUID;
	///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
};

//------ Folger 08/14/07 #10213 SUPPORT_3D_GRAPH_IN_DATA_INFO_WINDOW
static string _get_matrix_value_by_row(const MatrixObject &mo, int nRow, string &strX, string &strY)
{
	int nColNum = mo.GetNumCols();
	int nRowNum = mo.GetNumRows();
	double dXMin, dYMin, dXMax, dYMax;
	mo.GetXY(dXMin, dYMin, dXMax, dYMax);
	
	///------ Folger 09/02/2010 ORG-968-P1 RUNTIME_ERROR_IF_IMAGE_PLOT_WITH_COMPLEX_VALUE
	int		row = nRow / nColNum, col = nRow / nColNum;
	///------ End RUNTIME_ERROR_IF_IMAGE_PLOT_WITH_COMPLEX_VALUE
	double x = dXMin + (nRow % nColNum) * ((dXMax - dXMin) / (nColNum - 1));
	double y = dYMin + (nRow / nColNum) * ((dYMax - dYMin) / (nRowNum - 1));
	strX = ftoa(x);
	strY = ftoa(y);
	MatrixLayer ml;
	mo.GetParent(ml);
	int nIndex = mo.GetIndex();
	///------ Folger 09/02/2010 ORG-968-P1 RUNTIME_ERROR_IF_IMAGE_PLOT_WITH_COMPLEX_VALUE
	if ( mo.GetInternalData() == FSI_COMPLEX )
	{
		Matrix<complex> mat(ml, nIndex);
		return mat[row][col];
	}
	///------ End RUNTIME_ERROR_IF_IMAGE_PLOT_WITH_COMPLEX_VALUE
	Matrix mat(ml, nIndex);
	return mat.GetCellValue(x, y);
}
//------ End SUPPORT_3D_GRAPH_IN_DATA_INFO_WINDOW

///------ Folger 06/29/10 ORG-336 ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO
DataInfoCursor&		DataCursor(int nType);
///------ Folger 07/02/10 ORG-436-P4 DATA_INFO_CURSOR_FAILED_TO_GET_CATEGORICAL_DATA
//int					get_xyz_values(DataPlotStrings& dps, int nRow, double& x, double& y, double& z);
int					get_xyz_values(DataPlot& dp, int nRow, double& x, double& y, double& z);
///------ End DATA_INFO_CURSOR_FAILED_TO_GET_CATEGORICAL_DATA
///------ End ADD_BACK_CURSOR_SUPPORT_FOR_DATA_INFO