 /*-----------------------------------------------------------------------------*
 * File Name: XFbase.h				 											*
 * Creation: Yuri/CPY 															*
 * Purpose: X-Function base in VC level											*
 * Copyright (c) Originlab Corp.	2006										*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	ML 7/17/2006 GETTING_INPUT_DATA_DESCRIPTION_FROM_WITHIN_XFUNCTION_EXECUTION	*
 *	ML 7/19/2006 REMEMBERING_SETTINGS_IN_XFOPERATION_FOR_AUTO_UPDATE			*
 *	YuI 09/22/06 GETN_TREE_FOR_VARS_SET_EXTERNALLY_SHOULD_BE_CORRECT			*
 *	ML 12/15/2006 AUTO_SIZING_REPORT_TREE_ON_CONNECTING_OPERATION				*
 *	ML 5/18/2007 XFUNCTION_CLASS_NEW_ARRANGEMENT								*
 *	Hong 08/09/07 v8.0678 GET_SYSTEM_LABEL_FROM_OC_FOR_XF2DOC					*
 *	Sim 11-13-2007 GET_CREATED_OUTPUT_PAGE_INFO									*
 *	ML 1/9/2008 QA70-10917 MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC
 *	YuI 01/25/08 QA70-10998 CUSTOMIZATION_OF_XF_CREATED_TREE_FROM_OC			*
 *	Sim 08-19-2008 QA80-12050 GET_GUI_GETN_TREE_FOR_CHANGE_PARAM_MODE			*
 *	Folger 10/20/09 XF2GUI_SHOULD_NOT_SKIP_ANY_VARIABLES						*
 *	Folger 06/28/10 ORG-422 NEW_OC_CLASS_XFVARIABLE								*
 *	Folger 08/05/10 ORG-702-P1 CLEAR_OUTPUT_DATA_WITHOUT_ERROR_FOR_XF_OPERATION_RECALCULATE_IF_INPUT_IS_EMPTY
 *------------------------------------------------------------------------------*/

#ifndef _X_FUNCTION_BASE_H_
#define _X_FUNCTION_BASE_H_

#define STR_CREATOR_ATTRIB					"Creator"  /// Iris 9/15/05

/// ML 1/9/2008 QA70-10917 MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC
#define		DEFAULT_XFVERSION_LAST_TIME_RUN			0.0		// 0.0 means "not applicable", like when running it for the first time
																
#define		STR_ATT_OP_XFVER						"XFVER"
/// end MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC

/// AW 01/29/08 QA80-11002 GET_SAME_DEFAULT_VALUE_FOR_XF_VAR
enum {
	XF_GET_SIMPLE_DEFAULT_VALUE = 0x0001,
	///------ Folger 10/20/09 XF2GUI_SHOULD_NOT_SKIP_ANY_VARIABLES
	XF_GET_ALL_VARIABLES		= 0X0002,
	///------ End XF2GUI_SHOULD_NOT_SKIP_ANY_VARIABLES
};
/// END GET_SAME_DEFAULT_VALUE_FOR_XF_VAR

#ifdef __AFX_H__
	//--------- CPY 5/17/07 QA70-9794 XF_SEPARATE_INTO_TWO_CLASSES_AND_CACHE
	//class OCXFunction;
	//#define XFBase		OCXFunction
	class OCXF;
	#define XFBase OCXF;
	//---------
#else

#include <xfutils.h> //CPY 5/8/2007 QA70-9566 OUTPUT_TO_RESULTS_LOG_CHECKBOX_IN_GETN

#pragma dll(@OK)


//comments last updated by Joseph 08/07/07
/** >Composite Data Types
	The class allows calling XFunctions.
Example1:
	// The example shows how to call an xfunction via OriginC, by passing arguments one by one.
	#include	<XFbase.h>
	void	Example_1_call_xf_from_OC(int nSize = 25, int nSeed = 77)
	{
		string		strXFNameToCall = "stats";
		
		XFBase		xf(strXFNameToCall);
		if ( !xf )
		{
			out_str("Failed to load xfunction.");
			return;
		}
		
		vector		vv;
		// Generate data as a normal distribution with mean = 0, and sd = 1:
		vv.Normal(nSize, nSeed);
	
		double		mean, sd, min, max, sum;
		int			n;
		// Setting individual argument by name:
		if ( !xf.SetArg("x", vv) )
		{
			out_str("Failed to set arguments.");
			return;
		}
		
		// Setting individual argument by name:
		if ( !xf.SetArg("mean", mean) )
		{
			out_str("Failed to set arguments.");
			return;
		}
		
		// Setting individual argument by index:
		if ( !xf.SetArg(2, sd) )
		{
			out_str("Failed to set arguments.");
			return;
		}
		
		// Setting individual argument by index:
		if ( !xf.SetArg(3, n) )
		{
			out_str("Failed to set arguments.");
			return;
		}
		
		// Setting individual argument by name:
		if ( !xf.SetArg("min", min) )
		{
			out_str("Failed to set arguments.");
			return;
		}
		
		// Setting individual argument by name:
		if ( !xf.SetArg("max", max) )
		{
			out_str("Failed to set arguments.");
			return;
		}
		
		// Setting individual argument by index:
		if ( !xf.SetArg(6, sum) )
		{
			out_str("Failed to set arguments.");
			return;
		}
		
		if ( !xf.Evaluate() )
		{
			out_str("Evaluation failed.");
			return;
		}
		
		printf("mean = %lf\n"
				"sd = %lf\n"
				"n = %ld\n"
				"min = %lf\n"
				"max = %lf\n"
				"sum = %lf\n",
				mean, sd, n, min, max, sum);
	
		return;
	}
	
Example2:
	// The example shows how to call an xfunction via OriginC, by passing arguments in one call.
	#include	<XFbase.h>
	void	Example_2_call_xf_from_OC(int nSize = 25, int nSeed = 77)
	{
		string		strXFNameToCall = "stats";
		
		XFBase		xf(strXFNameToCall);
		if ( !xf )
		{
			out_str("Failed to load xfunction.");
			return;
		}
		
		vector		vv;
		vv.Normal(nSize, nSeed);
	
		double		mean, sd, min, max, sum;
		int			n;
		if ( !xf.SetArgs(vv, mean, sd, n, min, max, sum) )
		{
			out_str("Failed to set arguments.");
			return;
		}
		
		if ( !xf.Evaluate() )
		{
			out_str("Evaluation failed.");
			return;
		}
		
		printf("mean = %lf\n"
				"sd = %lf\n"
				"n = %ld\n"
				"min = %lf\n"
				"max = %lf\n"
				"sum = %lf\n",
				mean, sd, n, min, max, sum);
	
		return;
	}
	
*/
class	XFBase		:	public OriginObject//public	TreeNode   //--------- CPY 5/17/07 QA70-9794 XF_SEPARATE_INTO_TWO_CLASSES_AND_CACHE
{
public:
	XFBase(LPCSTR lpcszName = NULL);
	
	XFBase(TreeNode& trXF, BOOL bCompile = false, BOOL bPrepareVars = true, BOOL bInternal = FALSE);
	
	~XFBase();

public:
	/**
	*/
	BOOL	SetInternal(BOOL bSet = TRUE);

	/**
	*/
	BOOL	IsInternal();

	/**
	*/
	BOOL	Init(TreeNode& trXF, BOOL bCompile = false, BOOL bPrepareVars = true, BOOL bInternal = FALSE);

	/**
	*/
	/// ML 7/19/2006 REMEMBERING_SETTINGS_IN_XFOPERATION_FOR_AUTO_UPDATE
	//BOOL	Load(LPCSTR lpcszName, DWORD dwCntrl, TreeNode& trXF = NULL, BOOL bCompile = true, BOOL bSkipHelpNodes = false, BOOL bCreateVars = true);
	BOOL	Load(LPCSTR lpcszName, DWORD dwCntrl, TreeNode& trXF = NULL, BOOL bCompile = true, BOOL bSkipHelpNodes = false, BOOL bCreateVars = true, const TreeNode& trGetN = NULL);
	/// end REMEMBERING_SETTINGS_IN_XFOPERATION_FOR_AUTO_UPDATE

	/**
	*/
	int		Compile();

	/**
	*/
	int		InitWithInfo(TreeNode &trXF, TreeNode &trAux, UINT nUID, TreeNode &trUser, UINT wParam, LONG lParam);

	/**
	*/
	///---Sim 11-13-2007 GET_CREATED_OUTPUT_PAGE_INFO
	//BOOL	ApplyTheme(LPCSTR lpcszPath, TreeNode& trTheme = NULL);
	BOOL	ApplyTheme(LPCSTR lpcszPath, TreeNode& trTheme = NULL, BOOL bGetNTree = false, BOOL bIgnoreCheckPredefinedTypeOnly = false);
	///---END GET_CREATED_OUTPUT_PAGE_INFO

	
	/**
	*/
	//	BOOL	UpdateFromOperationRanges(DataRange *pdrInput, Array<DataRange&>* parrOutputs);
	BOOL	UpdateOutputUIDs(vector<int>& vUIDs);

	/**
	*/
	BOOL	ResetArg(LPCSTR lpcszName);

	/**
	*/
	BOOL	ResetArg(int nVarIndex);

	/**
	*/
	BOOL	SetArg(LPCSTR lpcszName, vector& var);
	
	/**
	Remarks:
		Push matrix on stack
	*/
	BOOL	SetArg(LPCSTR lpcszName, matrix& var);
	
	/**
	Remarks:
		Push int on stack
	*/
	BOOL	SetArg(LPCSTR lpcszName, int& var);
	
	/**
	Remarks:
		Push string on stack
	*/
	BOOL	SetArg(LPCSTR lpcszName, string& var);
	
	/**
	Remarks:
		Push double on stack
	*/
	BOOL	SetArg(LPCSTR lpcszName, double& var);
	
	/**
	Remarks:
		Push DataRange on stack
	*/
	
	/// YuI 03/19/07 QA70-9503 MERGE_SELFCREATING_RANGE_INTO_COKPOLYRANGE
	//	BOOL	SetArg(LPCSTR lpcszName, SelfCreatingRange& var);
	BOOL	SetArg(LPCSTR lpcszName, DataRange& var);
	/// end MERGE_SELFCREATING_RANGE_INTO_COKPOLYRANGE
	
	/**
	Remarks:
		Push MatrixObject on stack
	*/
	BOOL	SetArg(LPCSTR lpcszName, OriginObject& var);
	
	
	/**
	Remarks:
		Push FileLink on stack
	*/
	BOOL	SetArg(LPCSTR lpcszName, FileLink& var);

	/**
	Remarks:
		Push TreeNode on stack
	*/
	BOOL	SetArg(LPCSTR lpcszName, TreeNode& var);

	/**
	*/
	BOOL	SetArg(int nVarIndex, vector& var);
	
	/**
	Remarks:
		Push matrix on stack
	*/
	BOOL	SetArg(int nVarIndex, matrix& var);
	
	/**
	Remarks:
		Push int on stack
	*/
	BOOL	SetArg(int nVarIndex, int& var);
	
	/**
	Remarks:
		Push string on stack
	*/
	BOOL	SetArg(int nVarIndex, string& var);
	
	/**
	Remarks:
		Push double on stack
	*/
	BOOL	SetArg(int nVarIndex, double& var);
	
	/**
	Remarks:
		Push DataRange on stack
	*/
	/// YuI 03/19/07 QA70-9503 MERGE_SELFCREATING_RANGE_INTO_COKPOLYRANGE
	//	BOOL	SetArg(int nVarIndex, SelfCreatingRange& var);
	BOOL	SetArg(int nVarIndex, DataRange& var);
	/// end MERGE_SELFCREATING_RANGE_INTO_COKPOLYRANGE
	
	/// YuI 01/25/08 QA70-10998 CUSTOMIZATION_OF_XF_CREATED_TREE_FROM_OC
	BOOL	GetXFCreatedTree(LPCSTR lpcszName, TreeNode& tr);
	/// end CUSTOMIZATION_OF_XF_CREATED_TREE_FROM_OC
	
	//comments last updated by Joseph 08/07/07
	/**
		Set any OriginObject derived types, like MatrixObject, GraphLayer, Worksheet, Page etc.
	Example1:
		// this example shows how to call an XF to place axis scroll controls onto a graph
		#include <xfbase.h>	// this is the header file you need to include
		void test_calling_by_layer()
		{
			GraphLayer gl = Project.ActiveLayer();
			XFBase xf("add_xyscale_obj");
			if( xf )
			{
				//add_axis_scroller has two arg, 1st is GraphLayer and 2nd is axis index, which is default to X axis
				if( xf.SetArg(0, gl) )
					xf.Evaluate();
			}
		}
	*/
	BOOL	SetArg(int nVarIndex, OriginObject& var);
	
	
	/**
	Remarks:
		Push FileLink on stack
	*/
	BOOL	SetArg(int nVarIndex, FileLink& var);

	/**
	Remarks:
		Push TreeNode on stack
	*/
	BOOL	SetArg(int nVarIndex, TreeNode& var);

	/**
	*/
	BOOL	SetArgs(...);
	
	/**
		Get the last error of XFunction engine
	Return:
		TRUE if successful, FALSE otehrwise
	*/
	BOOL	GetLastError(int& nCode, string& strMessage = NULL);

	/**
		Get the last auxiliary error code of XFunction engine
	Return:
		TRUE if successful, FALSE otehrwise
	*/
	BOOL	GetLastErrorAux(int& nCode);

	//--- CPY 1/27/06
	
	/**
		Execute X-Function through the same mechanism as running from LabTalk. 	before_execute event is called and may open dialog if needed
	*/
	int		ExecuteLabTalk(LPCSTR lpcszArgs, vector<string>* pvsVarValues, LPVOID lpRetData = NULL, int nRetDataXVT = XVT_INT, int* lpOCerr = NULL, DWORD dwCntrl = 0, int nRecalculate = AU_NONE);
	/**
		Execute X-Function similar to ExecuteLabTalk, and before_execute is called but will not open dialog
	*/
	BOOL	Run(int nAutoUpdate, TreeNode& trGetN = NULL, LPVOID lpRetData = NULL, int nRetDataXVT = XVT_INT, int* lpOCerr = NULL, DWORD dwCntrl = 0);
	/**
		Execute X-Function without calling before_execute and will not open dialog
	*/
	///---Sim 11-13-2007 GET_CREATED_OUTPUT_PAGE_INFO
	//BOOL	Evaluate(DWORD dwCntrl = 0);
	BOOL	Evaluate(DWORD dwCntrl = 0, TreeNode& trVarRealResults = NULL);
	///---END GET_CREATED_OUTPUT_PAGE_INFO

	/**$
		Execute X-Function from Recalculate update
	*/
	/// ML 1/9/2008 QA70-10917 MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC
	//BOOL	Evaluate(DataRange *pdrInput, Array<DataRange&>* parrOutputs, DWORD dwCtrl = 0, vector<uint> *pvMapIdsToUIDs = NULL, TreeNode* pGetN = NULL);
	///------ Folger 08/05/10 ORG-702-P1 CLEAR_OUTPUT_DATA_WITHOUT_ERROR_FOR_XF_OPERATION_RECALCULATE_IF_INPUT_IS_EMPTY
	//BOOL	Evaluate(DataRange *pdrInput, Array<DataRange&>* parrOutputs, DWORD dwCtrl = 0, vector<uint> *pvMapIdsToUIDs = NULL, TreeNode* pGetN = NULL, double rXFVersionLastTime = DEFAULT_XFVERSION_LAST_TIME_RUN);
	BOOL	Evaluate(DataRange *pdrInput, Array<DataRange&>* parrOutputs, DWORD dwCtrl = 0, vector<uint> *pvMapIdsToUIDs = NULL, TreeNode* pGetN = NULL, double rXFVersionLastTime = DEFAULT_XFVERSION_LAST_TIME_RUN, OUID nOpUID = 0);
	///------ End CLEAR_OUTPUT_DATA_WITHOUT_ERROR_FOR_XF_OPERATION_RECALCULATE_IF_INPUT_IS_EMPTY
	/// end MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC

	BOOL 	SetVarData(int nVar, int nVal);
	BOOL 	SetVarData(LPCSTR lpcszName, LPCSTR lpcszVal);

	//comments last updated by Joseph 08/07/07
	/**
		Set X-Function variable option string
		Parameters:
			lpcszName = [input] variable name
			cOptionChar = [input] Option String character, like 'N' for name, 'A' for auto update
			lpcszOptionVal = [input] value to set
			bTempChange = [input] change XF for the remaining Origin session if set to false. 
		Example:
			//you can create a xfuntion test_var with just one integer variable x
			#include	<XFbase.h>
			void xf_set_option_str()
			{
				XFBase xf("test_var");
				if( xf )
				{
					if( xf.SetVarData(0, 2) )
					{
						xf.SetOptionString("x", 'N', "(Calculated Results)");
						xf.Evaluate();
					}
				}
			}

	*/
	BOOL	SetOptionString(LPCSTR lpcszName, int cOptionChar, LPCSTR lpcszOptionVal, BOOL bTempChange = true);
	/**
		get XF variable info as arrays also get TreeNode variables if any
	Parameters:
		dwCntl = [input], default value is 0. If it is XF_GET_SIMPLE_DEFAULT_VALUE, for XYRange data type default value just be one dimension, like <NEW> insetad of <NEW><NEW><NEW>
	Return:
		< 0 if error, return number of TreeNode variables with info to display otherwise
	Example:
		BOOL xf_getvars(string strname = "smooth")
		{
			string strOxfPath;
			// when xf has no path, which is most cases, we use ORIGIN_PATH_UNDEF so internally it will do searching
			int nLocation = okutil_find_file_from_composite_name(&strOxfPath, strname, SUPPORTFILE_XF, ORIGIN_PATH_UNDEF);
			if(ORIGIN_PATH_UNDEF  == nLocation)
				return FALSE;
			
			Tree trXF;
			if( !okutil_xft_Load(&trXF, strOxfPath) )
				return false;
			
			XFBase xf(trXF, false);
			
			vector<string> vsVarNames, vsVarDefaultVals, vsVarTypes;
			Tree trRuntime;
			bool bVarTypesAddRef = true;
			vector<int> vnIO;
			xf.GetVariables(vsVarNames, vsVarDefaultVals, vsVarTypes);
			
			xf.GetVariables(vsVarNames, vsVarDefaultVals, vsVarTypes, bVarTypesAddRef, vnIO, trRuntime);
			
			return true;
		}
	*/
	/// AW 01/29/08 QA80-11002 GET_SAME_DEFAULT_VALUE_FOR_XF_VAR
	//int	GetVariables(vector<string>& vsNames, vector<string>& vsValData = NULL, vector<string>& vsValTypes = NULL, BOOL bVarTypesAddRef = false, vector<int>& vnIO = NULL, TreeNode& trRuntime = NULL);
	int	GetVariables(vector<string>& vsNames, vector<string>& vsValData = NULL, vector<string>& vsValTypes = NULL, BOOL bVarTypesAddRef = false, vector<int>& vnIO = NULL, TreeNode& trRuntime = NULL, DWORD dwCntl = 0);
	/// AW 01/29/08 QA80-11002 GET_SAME_DEFAULT_VALUE_FOR_XF_VAR
	//----

	/// Hong 08/09/07 v8.0678 GET_SYSTEM_LABEL_FROM_OC_FOR_XF2DOC
	/**
		get XF variable label with language specified and return it's system label or not
	Parameters:
		lpcszName = [input] variable name
		strLabel = [output] ouput string to receive variable label
		nLang = [input] specify language
	Return:
		true if variable label is system label, otherwise return false
	Example:
		void xf_info(string strname = "smooth")
		{
			XFunction xf;
			if(!xf.Load(NULL, strname))
			{
				out_str("XF not found");
				return;
			}
			string strXFDesc = xf.GetHelpText(IDV_HELP_DESCRIPTION, _get_current_language()); 
			printf("Description:%s\n", strXFDesc);
			out_str("Variables:");
			vector<string> vsVarNames, vsVarLabel;
			xf.GetVariables(vsVarNames);
			
			for (int ii = 0; ii < vsVarNames.GetSize(); ii++)
			{
				string strLabel;
				printf("v%d: %s -> ",ii+1, vsVarNames[ii]);
				if(xf.GetVarLabel(vsVarNames[ii], strLabel))
					out_str("<system label>");
				else
					out_str(strLabel);
			}
		}
	*/
	BOOL	GetVarLabel(LPCSTR lpcszName, string& strLabel, int nLang = -1);
	/// end GET_SYSTEM_LABEL_FROM_OC_FOR_XF2DOC

	/**
	*/
	BOOL	IsAutoUpdatePossible();
	
	/// ML 5/18/2007 XFUNCTION_CLASS_NEW_ARRANGEMENT
	/**$
	*/
	BOOL	GetInputRangeAdditionalDataNode(TreeNode &trNode, BOOL bCreate = FALSE);

	/**$
	*/
	void	RemoveInputRangeAdditionalDataNode();
	/// end XFUNCTION_CLASS_NEW_ARRANGEMENT

	int		Construct(TreeNode& tr, LPCSTR lpcszVarName = NULL);

	BOOL	OpenGetNDialog(TreeNode& trGetN = NULL, BOOL bCallBeforeExecute = true);
	
	/// YuI 09/22/06 GETN_TREE_FOR_VARS_SET_EXTERNALLY_SHOULD_BE_CORRECT
	BOOL	UpdateLastUsed(int nAutoUpdate, DWORD dwCntrlFromRunXF);
	/// end GETN_TREE_FOR_VARS_SET_EXTERNALLY_SHOULD_BE_CORRECT
	
	int InvokeBeforeExecute(TreeNode& trGetN, DWORD dwCntrl, int nEventID = XF_GETN_SIMPLE);//------- CPY 12/5/06 XF_BAR_ALSO_NEED_TO_HAVE_CORRECT_EVENTS

	/// ML 12/15/2006 AUTO_SIZING_REPORT_TREE_ON_CONNECTING_OPERATION
	/**$
	*/
	void	OnConnectOperation();
	/// end AUTO_SIZING_REPORT_TREE_ON_CONNECTING_OPERATION
	
	//---- CPY 1/30/2007 IMPORT_FILTER_APPLY_TO_THEME_NEED_GETN_TREE
	///---Sim 08-19-2008 QA80-12050 GET_GUI_GETN_TREE_FOR_CHANGE_PARAM_MODE
	//BOOL GetGUI(Tree& trRoot, TreeNode& trGetN, int nAddRecalculate = XFGETN_EX_FOLLOW_XF, int nAddResultsLogOutput = XFGETN_EX_FOLLOW_XF);
	BOOL GetGUI(Tree& trRoot, TreeNode& trGetN, int nAddRecalculate = XFGETN_EX_FOLLOW_XF, int nAddResultsLogOutput = XFGETN_EX_FOLLOW_XF, DWORD dwCntrl = 0);
	///---END QA80-12050 GET_GUI_GETN_TREE_FOR_CHANGE_PARAM_MODE
	BOOL SetGUI(const TreeNode& trGetN);
	//----
	
	/**
		Get XF varaible Combostring info, if bRaw = TRUE, get original value, otherwise get processed combo string. Processing will remove Enumlist. 
	*/
	string GetComboString(string strVar, StringArray* psaCombo = NULL, BOOL bRaw = TRUE);
	/**
		Get XF varaible EnumList info. 
	*/
	string GetEnumList(string strVar, StringArray* psaEnumList = NULL );

};

///------ Folger 06/28/10 ORG-422 NEW_OC_CLASS_XFVARIABLE
class XFVariable : public OriginObject
{
public:
	XFVariable(TreeNode& trVar);
	
	BOOL	IsAccessibleFromLT();
	BOOL	IsAlwaysGenerateLTScript();
};
///------ End NEW_OC_CLASS_XFVARIABLE


#endif //#ifndef __AFX_H__
#endif //_X_FUNCTION_BASE_H_