#pragma once
#include "SecsBase.h"
//#include "SecsBase300.h"
#include "Group.h"

#ifdef DMS_300MM
#include "SecsBase300.h"
#endif



//////////////////////////////////////////////////////////////////////////
// 设备的使用的API接口类


//////////////////////////////////////////////////////////////////////////
// SECS/GEM API接口类
// 客户只需使用到该类

class CSecsEquip
{	
public:
	CSecsEquip();

public:
	// 开始：初始化自身对象      
	// 请勿设置该函数的参数，参数作为保留使用
	RcResult Start(std::string pServerAddr = "local", int nPort = 7000);
	void SecsEnable(bool bEnable);		// 启用/禁用 SECS功能

	// 终止：释放自身对象 
	void Abort();
		
	// 通讯控制
	RcResult CommEnable();				// 启用通信    
	RcResult CommDisable();				// 关闭通信
	RcResult CommIsEnable(bool& bEnable);		// 通讯是否开启
	RcResult GetCommState(COMM_STATE& nState);	// 获取通讯状态

	// 控制状态
	RcResult SetControlMode(CONTROL_MODE nState);				// 设置控制状态,符合semi标准
	RcResult SetControlModeForce(CONTROL_MODE nState);			// 强制设置控制状态，不经过Host允许
	CONTROL_MODE GetControlMode();								// 获取设置的状态
	RcResult GetControlState(CONTROL_STATE& nState);			// 获取控制状态
	RcResult ActiveRequestOnline();								// 主动请求在线，在线状态通过SetControlState设置
	
	// 授权
	RcResult GetLicenseLevel(__int32& nLevel);			// 获取许可授权级别
	RcResult GetMaxRunCount(__int32& nCount);			// 获取允许运行个数
	RcResult GetMaxRunDataPoint(__int32& nCount);		// 获取允许运行数据点(变量、事件、警报分别计算)

	// 设置/获取客户数据指针
	void SetClientData(void* pClientData);
	void* GetClientData();

	// 加载数据		
	RcResult LoadDataByCsvFile(std::string pDir = "");	// 加载Csv数据
	RcResult LoadProtocolConfig(std::string pDir = "");		// 加载SECS配置

/////////////////////////////////////////
// 设置参数, 必须			
	RcResult SetIP(std::string ip);				// 设置tcp/ip连接IP, 被动不需要设置
	std::string GetIP();

	RcResult SetPassive(bool bPassive);		// 设置tcp/ip连接被动/主动模式
	bool GetPassive();

	RcResult SetPort(int port);				// 设置tcp/ip连接端口
	int GetPort();

	RcResult SetDeviceID(int nDeviceID);	
	RcResult GetDeviceID(int& nDeviceID);

	// 设置超时
	RcResult SetT1(int nTimeout);	// 设置T1超时
	RcResult SetT2(int nTimeout);	// 设置T2超时
	RcResult SetT3(int nTimeout);	// 设置T3超时
	RcResult SetT4(int nTimeout);	// 设置T4超时
	RcResult SetT5(int nTimeout);	// 设置T5超时
	RcResult SetT6(int nTimeout);	// 设置T6超时
	RcResult SetT7(int nTimeout);	// 设置T7超时
	RcResult SetT8(int nTimeout);	// 设置T8超时

	RcResult SetMDLN(std::string pMDLN);				// 设备型号
	RcResult SetSOFTREV(std::string pSOFTREV);		// 软件版本

	RcResult SetEnableLog(bool bEnable);		// 启用Log记录,默认关闭
	RcResult SetLogDir(std::string pDir);		// 设置Log日志目录
	RcResult SetAutoDeleteLog(int nDay);		// 设置自动删除Log日志目录，nDay小于等于0，代表不删除log
	void EnableRuntimeTrace(bool bEnable);		// 启用运行过程中的LogTrace,追查BUG等

//////////////////////////////////////////////////////////////////////////
// 功能

	// 报警内容
	RcResult AlarmListGet(std::vector<ALARM_DATA>& ved);		// 报警列表获取
	RcResult AlarmAdd(int nALID, std::string pALTX);			// 增加报警
	RcResult AlarmAdd(int nALID, std::string pALTX, int nAlarmSetCEID, int nAlarmClearCEID, int nCategory);	// 添加报警
	RcResult AlarmAdd(int nALID, std::string pALTX, int nAlarmSetCEID, int nAlarmClearCEID, bool bEnable, int nCategory, bool bAddEvent);	// 添加报警
	RcResult AlarmEnable(int nALID, bool bEnable);		// 启用报警	
	RcResult AlarmSet(int nALID, bool bSet);			// 设置报警
	RcResult AlarmSetAll(bool bSet);					// 设置触发所有的报警
	RcResult AlarmNotifyEventMode(ALARM_NOTIFY_EVENT_MODE nMode);	// 报警发生后的通知模式，默认都通知


	// 事件内容	
	RcResult EventPos(int nCEID, bool bWaitReply = false);						// 事件发送: CEID 
	RcResult EventPos(std::string EventName, bool bWaitReply = false);				// 事件发送: 事件名称 		
	RcResult EventAdd(int nCEID, std::string pDescription, std::string pEventName = "", bool bEnable = true);	// 增加事件列表	
	RcResult EventListGet(std::vector<EVENT_DATA>& ved);		// 事件列表获取		
	RcResult EventEnable(int nCEID, bool bEnable);										// 事件启用/禁用
	RcResult EventIsEnable(int nCEID, bool& bEnable);									// 事件是否启用/禁用
	RcResult EventDvvals(std::string pEventName, std::vector<std::string> &dvvalName);		// 事件DVVAL绑定
	RcResult EventDvvals(int nCEID, std::vector<int> &dvval);							// 事件DVVAL绑定
	RcResult EventDiscreteVarPos(int nCEID);			// 事件S6,F3发送: CEID


	//报表
	RcResult EventReportLink(int nECID, int report);						// 事件-报表关联
	RcResult EventReportLink(int nECID, std::vector<int>& report);			// 事件-报表关联
	RcResult EventReportUnlink(int nECID);									// 事件-报表取消关联
	RcResult ReportDefine(int nReport, std::vector<int> & listVarID);		// 报表定义
	RcResult ReportDefineGet(int nReport, std::vector<int> & listVarID);	// 获取报表定义
	RcResult ReportDelete(int nReport);										// 删除报表
	RcResult ReportUnlink(int nReport);										// 清除报表所有与之相关的事件
	RcResult ReportClear();													// 清除所有报告定义，并且清除所有事件与报告之间的并联								
	RcResult ReportStrictlyFollowStandard(bool bFollow);					// 报告严格按照标准规范处理：E5标准的处理及返回值
	RcResult ReportAutoSaveHostLinkConfig(bool bEnable);					// 报告保存服务器配置到本地

	// 变量内容	
	RcResult VariableAdd(int nVarID, std::string varName, std::string description, 
		std::string valueType, std::string initValue, std::string units, std::string varClass = "SV");		// 变量增加  
	
	RcResult VariableSet(int nVarID, std::string newValue);			// 设置变量新值  	 
	RcResult VariableGet(int nVarID, std::string& pValue);			// 获取变量的值 
	RcResult VariableListGet(std::vector<VARIABLE_DATA>& vvd);		// 变量列表获取
	RcResult VariableSetMethod(int nVarID, bool bCallback = true);				// 设置处理方法，统一方法
	RcResult VariableSetMethod(int nVarID, SecsVarValueProc *pCallback);		// 设置处理方法，指定回调


	// 常量
	RcResult ConstantsAdd(int nECID, std::string name, std::string description, std::string Type, 
		std::string Units, std::string MinValue, std::string MaxValue, std::string DefValue); // 添加常量      
	
	RcResult ConstantsGet(int nECID, std::string& pValue);			// 常量获取
	RcResult ConstantsSet(int nECID, std::string newValue);			// 设置变量新值  
	RcResult ConstantsInfoGet(std::vector<VARIABLE_DATA> &info);		// 获取常量信息
	RcResult ConstantsSetMethod(int nECID, bool bCallback = true);					// 设置处理方法，统一方法
	RcResult ConstantsSetMethod(int nECID, SecsConstantValueProc *pCallback);		// 设置处理方法，指定回调	
	RcResult ConstantChangeSendEventEnable(bool bEnable);		// 启用/禁用常量改变发送事件         

	// 发送终端服务
	RcResult SendSingleTerminal(std::string pContent);
	RcResult SendMultipleTerminal(std::vector<std::string> svContent);
	
	// 处理程序
	RcResult PPAllowHostDowmload(bool bAllow);			// 允许主机下载
	RcResult PPHandleMode(PP_HANDLE_MODE nMode);		// PP处理模式

	// 内置功能
	std::string GetRecipeDirectory();						// 获取程式目录	
	void SetRecipeDirectory(std::string dir);				// 设置程式目录
	RcResult ProcessProgramUpload(std::string ppid);			// 上传程式
	RcResult ProcessProgramDownload(std::string ppid);		// 请求下载程式	
	RcResult PPIsFolderDir(bool bFolder);				// 设置PP是文件夹目录	
	RcResult SetWinrarPath(std::string path);				// 设置winrar.exe目录
	RcResult PPSetFilenameExtension(std::string pFileExten);	// 设置扩展名
	
	
	// recipe 序列化
	RcResult PPFormatAdd(std::string pCmdCode, std::string pName, std::string pValueType);		// 参数对象添加 
	RcResult PPFormatSend(std::string ppid);					// PP序列化上传
	RcResult PPFormatRequest(std::string ppid);					// PP序列化下载
	RcResult PPFormatSetCodeMode(PP_FORMAT_MODE nMode);			// PP序列化设置模式

	// wafer map
	RcResult WaferMapUpload(WAFER_MAP pWaferMap);		// 晶圆图上传
	RcResult WaferMapDownload(WAFER_MAP& pRequstInfo, WAFER_MAP& pWaferMap);	// 晶圆图下传请求
	RcResult StripMapDownload(std::string pStripID, STRIP_MAP& pStripMap);			// 条带图下传请求
		
//////////////////////////////////////////////////////////////////////////
// 扩展型功能，特殊情形使用
	
	// 时间同步,默认启用
	// 必须以管理员运行软件才起作用
	void AutoResponseTimeSync(bool bAuto);			// 自动响应时间同步,	
	RcResult ActiveTimeSynchronizeRequest();		// 主动请求主机时间进行同步
	
	// 当设置远程控制响应扩展型时候，需要用户主动答复结果
	void RemoteCmdReply(std::string pReplyMailbox, REMOTE_REPLY nHCACK, std::list<ERROR_CODE_DESCRIPTION> listErrorCode);
	
	// 扩展操作
	RcResult SendSecsMsgAsync(int nStream, int nFunction, bool bReply, std::string pData, int64& nMsgID);
	RcResult SendSecsMsgSync(int nStream, int nFunction, bool bReply, std::string pData, std::string& pReplyData);
	RcResult SendReply(int nStream, int nFunction, int nTransactionID, std::string pData);
	
	RcResult MessageTypeAdd(int nStream, int nFunction, SecsMessageReceiveProc pCallback, void* pClientData);
	RcResult MessageTypeRemove(int nStream, int nFunction);

public:

	// 回调函数,基础
	SecsStateChangeProc* m_pStateChangeCallback;			// 状态改变回调
	SecsTerminalProc* m_pTerminalCallback;					// 终端信息回调
	SecsRemoteProc* m_pRemoteCallback;						// 远程控制回调
	SecsVarValueProc* m_pVarValueProc;						// 变量回调取值时，如果VariableSetMethod没有指定回调，则会调用该函数

	// 高级
	SecsRemoteProcEx* m_pRemoteExCallback;					// 远程控制回调,需要用户主动反馈结果，远程回调二选一
	SecsConstantsChangeProc* m_pConstantsChangeCallback;	// 常量改变回调
	SecsPPChangeNotifyProc* m_pPPChangeNotifyProc;			// 处理程序发生改变通知回调
	SecsClockProc* m_pClockProc;							// 时间改变回调
	SecsConstantValueProc* m_pConstantValueProc;			// 常量回调取值时，如果ConstantsSetMethod没有指定回调，则会调用该函数
	
	// 特殊使用
	SecsPPFormatValueProc* m_pPPFormatValueProc;					// 主机获取Recipe变量值
	SecsPPFormatChangeProc* m_pPPFormatChangeProc;					// 主机修改Recipe变量值
	SecsPPNameListProc* m_pPPNameListProc;							// PP名称列表获取
	SecsPPEventProc* m_pPPEventProc;								// 自定义PP事件处理
	SecsPPFormatValueDynamicProc* m_pPPFormatValueDynamicProc;		// 主机获取Recipe变量值，动态的值
	SecsPPFormatChangeDynamicProc* m_pPPFormatChangeDynamicProc;	// 主机更新Recipe变量值，动态的值

 
	// WaferMap
	SecsWaferMapSubstrateProc* m_pWaferMapSubstrateProc;	// StripMap处理

	SecsS9ErrorNotifyProc* m_pS9ErrorNotifyProc;			// S9处理完后，再通知客户

public:
	// 初始化回调处理对象
	// 不提供给用户使用的方法
	void OnStateChangeHandler(const char *data);						// 响应状态改变处理
	void OnTerminalHandler(std::string pReplyMailbox, std::string Data);			// 响应终端服务处理
	void OnRemoteHandler(std::string pReplyMailbox, const char *data);		// 响应远程命令处理
	void OnConstantsChangeHandler(const char *data);					// 响应常量改变处理
	void OnPPChangeNotifyHandler(const char *data);						// 响应处理程序改变通知
	void OnClockHandler(const char *data);								// 响应时间改变处理
	void OnVarValueHandler(std::string pReplyMailbox, std::string Data);				// 响应变量值请求处理
	void OnConstantValueHandler(std::string pReplyMailbox, std::string Data);			// 响应常量值请求处理
	void OnPPFormatValueHandler(std::string pReplyMailbox, std::string Data);			// 响应主机获取Recipe变量值
	void OnPPFormatValueDynamicHandler(std::string pReplyMailbox, std::string Data);	// 响应主机获取Recipe变量值
	void OnPPFormatChangeHandler(std::string pReplyMailbox, std::string Data);			// 响应主机修改Recipe变量值
	void OnPPFormatChangeDynamicHandler(std::string pReplyMailbox, std::string Data);	// 响应主机修改Recipe变量值
	void OnPPChangeCostomizeHandler(std::string pReplyMailbox, std::string Data);		// 响应PP自定义改变处理
	void OnS9ErrorNotifyHandler(std::string pReplyMailbox, std::string Data);			// 响应S9错误处理后通知
	void OnWaferMapSubstrateHandler(std::string pReplyMailbox, std::string Data);		// 响应Wafer信息处理

protected:
	/// 初始化SECS参数 
	RcResult InitSecsParament();

	// 初始化回调
	void InitCallback();

	void VarValueRequest(const char *varList, std::vector<std::string> &values);
	void ConstantValueRequest(std::string varList, std::vector<std::string> &values);
	void PPFormatValueRequest(std::string varList, std::vector<std::string> &values);
	void PPFormatValueDynamicRequest(const char *varList, std::vector<std::string> &values);
	PP_HANDLE_REPLY PPFormatValueChange(const char *varList, std::vector<std::string> values);

	long GetWaferMap(std::string pData, WAFER_MAP& pWaferMap);

protected:
	
#ifdef DMS_300MM
	CSecsBase300 m_impl;
#else
	CSecsBase m_impl;
#endif
	
private:

	// 连接参数
	std::string m_pIP;
	int m_nPort;
	bool m_bPassive;
	int m_nDeviceID; 

	// 客户数据
	void* m_pClientData;
		
	// 超时 (ms)
	int m_nT1;
	int m_nT2;
	int m_nT3;
	int m_nT4;
	int m_nT5;
	int m_nT6;
	int m_nT7;	
	// T8 is not used

	// 设备型号	Equipment Model Type	
	std::string m_pMDLN;

	// 软件版本号 Software revision code
	std::string m_pSOFTREV;

	// 程式路径（Host）
	std::string m_pRecipeDir;

	CONTROL_MODE m_nControlState;

	// 回调函数及互锁
	vCritical m_lockVarMethod;
	vCritical m_lockConstantMethod;
	vCritical m_lockPPFormat;
	vCritical m_lockPPChange;
	std::map<int,SecsVarValueProc*> m_mapVarValueCallback;
	std::map<int,SecsConstantValueProc*> m_mapConstantValueCallback;

	// 自动响应时间同步
	bool m_bAutoResponseTimeSync;

};


// 其他辅助函数
std::string GetCommunicationText(COMM_STATE e);		// 获取通讯状态文字
std::string GetControlText(CONTROL_STATE e);			// 获取控制状态文字
std::string UnicodeToAscii(std::wstring pUnicode);		// UNICODE 字符串转换 ANSI
std::wstring AsciiToUnicode(std::string pUnicode);		// ANSI 字符串转换 UNICODE











