/*------------------------------------------------------------------------------*
 * File Name: Page_Utils.cpp													*
 * Creation: July 25, 2003														*
 * Purpose: Define page utility functions										*
 * Copyright (c) OriginLab Corp. 2003											*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	RVD 9/3/2003 QA70-5078 v7.0682 PLOT_RANGE_APPLY								*
 *	ML 12/9/2003 QA70-5657 UTILITY_ORIGINC_FUNCTIONS_FOR_PLOT_CREATION			*
 *	AW 01/30/04 QA70-5657 v7.0811 TEMP_FIXING_MAKE_PLOTS_TREE					*					
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// Including the system header file Origin.h should be sufficient for most Origin
// applications and is recommended. Origin.h includes many of the most common system
// header files and is automatically pre-compiled when Origin runs the first time.
// Programs including Origin.h subsequently compile much more quickly as long as
// the size and number of other included header files is minimized. All NAG header
// files are now included in Origin.h and no longer need be separately included.
//
// Right-click on the line below and select 'Open "Origin.h"' to open the Origin.h
// system header file.
#include <Origin.h>
////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////
// Include your own header files here.


////////////////////////////////////////////////////////////////////////////////////
// Start your functions here.
static bool get_storage_and_section_names(string& strStorage, string& strSection, LPCSTR lpcszStorageSection)
{
	if( lpcszStorageSection )
	{
		string strStorageSection(lpcszStorageSection);
		if( 2 == strStorageSection.GetNumTokens('.') )
		{		
			strStorage = strStorageSection.GetToken(0, '.');
			strSection = strStorageSection.GetToken(1, '.');
			return true;
		}
	}
	return false;
}

bool info_get_section(OriginObject& obj, TreeNode& trSection, LPCSTR lpcszStorageSection)
{
	if( obj )
	{
		string strStorage, strSection;
		if( get_storage_and_section_names(strStorage, strSection, lpcszStorageSection) )
		{
			storage st;
			st = obj.GetStorage(strStorage);
			if( st )
				return st.GetSection(strSection, trSection);
		}
	}
	return false;
}

bool info_set_section(OriginObject& obj, TreeNode& trSection, LPCSTR lpcszStorageSection)
{
	if( obj )
	{
		string strStorage, strSection;
		if( get_storage_and_section_names(strStorage, strSection, lpcszStorageSection) )
		{
			storage st;
			st = obj.GetStorage(strStorage, true); // true = add if does not exist
			if( st )
				return st.SetSection(strSection, trSection);
		}
	}
	return false;
}

bool page_get_info_var_value(Page& pg, LPCSTR lpcszVarName, string& strVarVal, LPCSTR lpcszStorageSection)
{
	string strStorageSection("User.Variables");
	if( lpcszStorageSection )
		strStorageSection = lpcszStorageSection;

	Tree trSection;
	if( info_get_section(pg, trSection, strStorageSection) )
	{
		string strVarName(lpcszVarName);
		strVarName.MakeUpper();

		TreeNode trnVar;
		trnVar = trSection.GetNode(strVarName);
		if( trnVar )
		{
			strVarVal = trnVar.strVal;
			return true;
		}
	}
	return false;
}

bool page_set_info_var_value(Page& pg, LPCSTR lpcszVarName, LPCSTR lpcszVarVal, LPCSTR lpcszStorageSection)
{
	string strStorageSection("User.Variables");
	if( lpcszStorageSection )
		strStorageSection = lpcszStorageSection;

	Tree trSection;
	if( info_get_section(pg, trSection, strStorageSection) )
	{
		string strVarName(lpcszVarName);
		strVarName.MakeUpper();

		TreeNode trnVar;
		trnVar = trSection.GetNode(strVarName);
		if( !trnVar )
			trnVar = trSection.AddNode(lpcszVarName);
		if( trnVar )
		{
			trnVar.strVal = lpcszVarVal;
			return info_set_section(pg, trSection, strStorageSection);
		}
	}
	return false;
}

bool page_get_info_var_value(Page& pg, LPCSTR lpcszVarName, double& dVarVal, LPCSTR lpcszStorageSection)
{
	string strVarVal;
	if( page_get_info_var_value(pg, lpcszVarName, strVarVal, lpcszStorageSection) )
	{
		dVarVal = atof(strVarVal);
		return true;
	}
	return false;
}

bool page_set_info_var_value(Page& pg, LPCSTR lpcszVarName, double dVarVal, LPCSTR lpcszStorageSection)
{
	string strVarVal;
	strVarVal.Format("%f", dVarVal);
	return page_set_info_var_value(pg, lpcszVarName, strVarVal, lpcszStorageSection);
}

bool page_get_storage_str(Page& pg, LPCSTR lpcszName, string &strValue)
{
	if( pg && lpcszName )
	{
		vector<byte> vb;
		if( pg.GetMemory(lpcszName, vb) )
			return strValue.SetBytes(vb);
	}
	return false;
}

bool page_set_storage_str(Page& pg, LPCSTR lpcszName, LPCSTR lpcstrValue)
{
	if( pg && lpcszName && lpcstrValue )
	{
		string strValue(lpcstrValue);
		vector<byte> vb;
		if( strValue.GetBytes(vb) )
			return pg.SetMemory(lpcszName, vb);
	}
	return false;
}

int	gpage_get_plots(const GraphPage &pg, TreeNode &tr)
{
	if(pg == NULL)
		return 0;
	
	int				nCount = 0;
	
	tr.RemoveChild("DataPlots");
	TreeNode		trRoot = tr.AddNode("DataPlots");
	if (!trRoot.IsValid())
		return false;
	int nActiveLayerIndex = -1;
	int nRet = 0;
	foreach (GraphLayer lay in pg.Layers)
	{
		if (lay)
		{
			Tree		trLayer;
			int nn;

			/// RVD 9/3/2003 QA70-5078 v7.0682 PLOT_RANGE_APPLY
			//if (nn = lay.GetLayerContents(trLayer, GETLC_DATAPLOTS | GETLC_STYLE_HOLDERS))
			DWORD dwCntrl = GETLC_DATAPLOTS | GETLC_STYLE_HOLDERS;

			DWORD dwPlotView;

			if( dlg_load_registry(STR_PLOT_SETUP_DLG, STR_PLOT_VIEW, dwPlotView) )
			{
				if( dwPlotView & DPEDTVIEW_HIDE_LIMITS )
					dwCntrl |= GETLC_NO_LIMITS;
			}

			if( nn = lay.GetLayerContents(trLayer, dwCntrl) )
			/// end PLOT_RANGE_APPLY
			{
				//TreeNode	trDP = trLayer.DataPlots.Clone();
				TreeNode	trL = trLayer.FirstNode;
				TreeNode	trDP = trL.Clone();
				DWORD		dwLayerBits = lay.GetSystemParam(GLI_PCD_BITS);
				string strTemp = dwLayerBits;
				trDP.SetAttribute(STR_LAYER_TYPE_BITS, strTemp);
				//TreeNode	trLayer = trRoot.AddNode("Layer");					
				trRoot.AddNode(trDP);
				//trLayer = trDP;
				if(0==nRet)
					nRet = nn;
			}
			else
				ASSERT(FALSE);
		}
		else
			ASSERT(FALSE);
	}
	if(nRet)
	{
		nActiveLayerIndex = page_active_layer_index(pg);
		if(nActiveLayerIndex >= 0)
		{
			string strTemp = nActiveLayerIndex;
			trRoot.SetAttribute(STR_ACTIVE_LAYER, strTemp);
		}
	}
	return nRet;
}


int page_active_layer_index(Page& pg)
{
	Page activePg = Project.Pages();
	if(activePg.GetName() != pg.GetName())
		return -1;
	
	Layer lay = pg.Layers();
	
	return lay.GetIndex();
}

//------ CPY 10/11/04 MOVE_GRAPH_GET_INFO_TREE_TO_PAGE_UTILS
bool page_graph_get_info_tree(GraphLayer gl, TreeNode& trNode)
{
	if(!gl)
		return false;
	
	vector<string> vsWksNames;
	vector<uint>	vsDataPlots;
	uint iPlot = 1;// LabTalk index
	foreach(DataPlot dp in gl.DataPlots)
	{
		// we are trying to get wks name from a data plot
		// currently there is no clean way to do this
		string strName = dp.GetDatasetName();
		int nPos = strName.Find('_');
		string strWksName;
		if(nPos > 0)
			strWksName = strName.Left(nPos);
		else // check for matrices
			strWksName = strName;
		
		if(!strWksName.IsEmpty() && !is_in_list(strWksName, vsWksNames))
		{
			vsWksNames.Add(strWksName);
			vsDataPlots.Add(iPlot++);
		}
		
	}
	
	for(int ii = 0; ii < vsWksNames.GetSize(); ii++)
	{
		string str = vsWksNames[ii];
		Page pg(vsWksNames[ii]);
		string strLabel = pg.Label;
		if(!strLabel.IsEmpty())
			str += " - " + pg.Label;
		tree_add_info(trNode, pg, vsWksNames[ii], str, vsDataPlots[ii]);
	}
	
	return true;
}
//---- end MOVE_GRAPH_GET_INFO_TREE_TO_PAGE_UTILS

/// ML 12/9/2003 QA70-5657 UTILITY_ORIGINC_FUNCTIONS_FOR_PLOT_CREATION


// this function is needed in several classes, we should not call GetPlotTypeInfo directly, need all these additional fix up
int	get_plot_type_info(int nPlotID, int nPageType, DWORD dwTargetLayer, DWORD& dwAuxTypeInfo, DWORD& dwAuxPlotInfo, string& strColPattern)
{
	int nPlotType = 0;
	
	if(nPlotID)
		nPlotType = Project.GetPlotTypeInfo(nPlotID, dwAuxTypeInfo, dwAuxPlotInfo, strColPattern);
	if(nPageType)
	{
		if(EXIST_DATA == nPageType || EXIST_FUNC_PLOT == nPageType)
			dwAuxTypeInfo &= ~PCD_CAN_ADD_E_H_L;
		if(EXIST_FUNC_PLOT == nPageType)
			dwAuxTypeInfo |= PCD_NO_X;
	}
	
	if (PCD_LAYER_TRI == dwTargetLayer)
	{
		DWORD dwSaveModifiers = dwAuxTypeInfo & ( PCD_MODIFIER_SIZE | PCD_MODIFIER_COLOR );
		dwAuxTypeInfo = PCD_LAYER_TRI | PCD_EXACT_YCOLS | PCD_Z_PREFER_Y | PCD_GROUP_MULTI_YS | PCD_PREFER_X | PCD_CAN_ADD_E_H_L | PCD_HIDE_ERR_BARS;
		dwAuxTypeInfo |= dwSaveModifiers;
	}
	else if (PCD_LAYER_SMITH == dwTargetLayer)
		dwAuxTypeInfo |= PCD_HIDE_ERR_BARS;
	return nPlotType;
}

static	int		make_plots_tree(TreeNode &tr, int nPlotType, vector<string>	&vsWksPages, vector<string>	&vsLayers, vector<string> &vsCols, vector<uint> &vpdesig)
{
	DWORD			dwAuxTypeInfo, dwLTPlotInfo;
	string			strColPattern;
	uint			nExVal = 0;
	
	int				nn = get_plot_type_info(nPlotType, EXIST_WKS, 0, dwAuxTypeInfo, dwLTPlotInfo, strColPattern);
	/// AW 01/30/04 QA70-5657 v7.0811 TEMP_FIXING_MAKE_PLOTS_TREE
	// required by ML temp changing here
	//int				nRet = Project.MakeDataplotsTree(tr, nn, dwAuxTypeInfo, dwLTPlotInfo, strColPattern, nExVal, vpdesig, vsWksPages, vsLayers, vsCols, TRUE);
	int	nRet =  0 == Project.MakeDataplotsTree(tr, nn, dwAuxTypeInfo, dwLTPlotInfo, strColPattern, nExVal, vpdesig, vsWksPages, vsLayers, vsCols, TRUE);
	/// END TEMP_FIXING_MAKE_PLOTS_TREE
	
	return nRet;
}

/// AW 12/24/03 MORE_WORK_ON_ADD_PLOTS_TO_LAYER
// return: 
//		1) >0, the total number of plots added; 
//		2) =0 means "Failed to add dataplots.";
//      3) =-1 means "Cannot create plot tree.";
/// MORE_WORK_ON_ADD_PLOTS_TO_LAYER
int		add_plots_to_layer(GraphLayer &lay, int nPlotType, LPCSTR lpcszWksName, vector<string> &vsCols, vector<uint> &vpdesig)
{
	Tree			tr;
	vector<string>	vsWksPages;
	vector<string>	vsLayers;
	
	vsWksPages.Add(lpcszWksName);
	vsLayers.SetSize(1);
	
	
	int				nRet = make_plots_tree(tr, nPlotType, vsWksPages, vsLayers, vsCols, vpdesig);
	/// AW 12/24/03 MORE_WORK_ON_ADD_PLOTS_TO_LAYER
	/*
	if (!nRet)
	{
		out_str("Cannot create plot tree.");
		return -1;
	}
	*/
	if (0 != nRet)
		return -1;  // error, Cannot create plot tree 
	/// END MORE_WORK_ON_ADD_PLOTS_TO_LAYER
	TreeNode		trLayer = tr.FirstNode;
	int				nNumPlotsAdded = lay.AddPlots(trLayer, ADDPLOTSFROMTREE_NEW);
	if (nNumPlotsAdded <= 0)
	{
		/// AW 12/24/03 MORE_WORK_ON_ADD_PLOTS_TO_LAYER
		//out_str("Failed to add dataplots");
		return 0; //  error, Failed to add dataplots
		/// END MORE_WORK_ON_ADD_PLOTS_TO_LAYER
	}
	
	return nNumPlotsAdded;
}

/// end UTILITY_ORIGINC_FUNCTIONS_FOR_PLOT_CREATION
