#pragma once

 

//#include "bombax.h"
#include "robbase.h"

#include "SoftTrigger.h"
#include "gio.h"
#include "MotOpts.h"
 
#include "RobMot.h"

//机器状态
#define WD_MS_UNKNOWN   (-1)
#define WD_MS_STANDBY   0  //待机
#define WD_MS_RUNNING   1  //正在运行
#define WD_MS_PAUSED    2  //暂停, 

//mode 
#define WD_SM_UNKNOWN       -1  
#define WD_SM_FREE_RUN      1   
#define WD_SM_NORMAL_RUN    2   
#define WD_SM_HOME_E1       3   //外部回零运动模式
#define WD_SM_HOME_E2       4   //一次回零模式

   




#define WD_ACT_UNKNOWN          (-1)  //未知
#define WD_ACT_RESET_ZXY         0    //复位Z,X,Y 
#define WD_ACT_RESET_ZRXY        1    //复位.ZRXY
#define WD_ACT_RESET_ZXYY2       2    //复位.ZXYY2 
#define WD_ACT_RESET_XY          3    //复位XY
#define WD_ACT_RESET_X           4    //复位X 
#define WD_ACT_RESET             5    //单轴
#define WD_ACT_RESET_ZRXYY2      6    //复位.ZRXYY2 
 
#define WD_ACT_RESET_MAX         9 

#define WD_ACT_MOVE              11    //移动单轴
#define WD_ACT_STEP              12    //任意单轴步进 
#define WD_ACT_MOVE_XY           13    //
#define WD_ACT_MOVE_XYZ          14    // 
#define WD_ACT_MOVE_XY2          15    //
#define WD_ACT_MOVE_XY2Z         16    //
#define WD_ACT_MOVE_ANY2         17   //任意2绝对移动 

#define WD_ACT_HOME              20    //任意单轴回零 
#define WD_ACT_HOME_XY           21    // 
#define WD_ACT_HOME_XY2          22    //
#define WD_ACT_HOME_ZXY          23    //
#define WD_ACT_HOME_XYY2         24    //
#define WD_ACT_HOME_ZRXY         25    //
#define WD_ACT_HOME_ZXYY2        26    //
#define WD_ACT_HOME_XYZ          27    //
#define WD_ACT_HOME_ANY          28    //任意2,3,4轴回零
#define WD_ACT_HOME_MAX          30    //


//#define WD_ACT_REPEAT_MOVE       19    //x,y轴重复运动，用于验证机械精度


#define WD_ACT_USER_EX           57    //用户自定义动作


//自定义消息事件
#define WD_ON_ACT_START         (WM_USER + 1301) //13月01号，避开按月份编号的自定义消息
#define WD_ON_ACT_STOP          (WM_USER + 1302) //13月02号，避开按月份编号的自定义消息


#define WD_MAX_DELAY_TIME          5999

//最多触发器数量
#define WD_MAX_TRIGGER_COUNT       16

//scene type
#define WD_ST_HOME      0
#define	WD_ST_EDIT      1
//扩展场景
//#define	WD_ST_SIMU      2
//#define	WD_ST_WORK      3
//#define	WD_ST_TINY      4





class ROBBASE_API CWorkDesk
{
public:
	CWorkDesk(void);
	virtual ~CWorkDesk(void);

	virtual BOOL Start(int act, BOOL bCheckHome  , int* pErrCode  );
	virtual void Stop();

	//自由启动，不通过action调用运动函数
	//直接调用
	BOOL StartFree(int* pErrCode);
	void StopFree();



	virtual BOOL IsReady(int axes);

	BOOL Delay(int timeout);

	int GetCurState(){ return m_nCurState;};
	int GetCurAction(){ return m_nCurAct; };
	int GetCurMode() { return m_nCurMode; };

	virtual void Reset();

	//获取当前位置
	virtual BOOL GetCurPos(double* pX, double* pY, double* pZ, int* pErrCode );
	virtual BOOL GetCurPos(double* pX, double* pYorY1, double* pZ, double * pRorY2, int* pErrCode );
	virtual BOOL GetCurPos(int axis, double * pPos, int* pErrCode );

	//回零, 不需要调用等待函数，不产生消息
	virtual BOOL GoHome(int axis, int* pErrCode);
	virtual BOOL GoHomeXY(int* pErrCode);  //x,y同时回零点
	virtual BOOL GoHomeXY2(int* pErrCode); //x,y2同时回零点
	virtual BOOL GoHomeXYY2(int* pErrCode);//x,y, y2同时回零点
	virtual BOOL GoHomeZXY(int* pErrCode); //z先回零点,y, y2同时回零点
	virtual BOOL GoHomeZRXY(int* pErrCode);//z先回零点, 然后r回零点, 最后x, y同时回零点
	virtual BOOL GoHomeZRXYY2(int* pErrCode);//z先回零点, 然后r回零点, 最后x, y, y2同时回零点
	virtual BOOL GoHomeZXYY2(int* pErrCode); //z先回零点, 然后x, y, y2同时回零点
	//回零任意两轴 
	virtual BOOL GoHomeAny2(int axes, int* pErrCode) ; //任意两轴回零
	virtual BOOL GoHomeAny3(int axes, int* pErrCode) ; //任意3轴回零
	virtual BOOL GoHomeAny4(int axes, int* pErrCode) ; //任意4轴回零
	virtual BOOL GoHomeAny(int axes, int* pErrCode) ; //任意多轴回零




	//运动, 不需要调用等待函数，不产生消息
	virtual BOOL MoveSingleAxisTo(int axis, double pos,  BOOL bAbsolute, int* pErrCode);
	virtual BOOL MoveXYToPos(double x, double y, int* pErrCode );
	virtual BOOL MoveXY2ToPos(double x, double y2, int* pErrCode );
	virtual BOOL MoveXYZToPos(double x, double y, double z, int* pErrCode);
	virtual BOOL MoveXY2ZToPos(double x, double y, double z, int* pErrCode);

	//移动任意两轴 
	virtual BOOL MoveAny2ToPos(int axes, double x, double y, int* pErrCode) ;
	//同步移动@1229
	virtual BOOL MoveAny2ToPos(int axes, double x, double y, BOOL bAbsolute, int* pErrCode) ;
	//end of @1229


	//圆弧和圆
	virtual BOOL MoveArcAny2(int axes, double endX, double endY, double radius, BOOL bBigArc, int dir, int* pErrCode) ;
	virtual BOOL MoveCircleAny2(int axes, double centerX, double centerY, double startX , double startY, int dir,  int* pErrCode) ;

	//缓冲区执行多段线
	//virtual BOOL MovePolyline(int axes, double centerX, double centerY, double startX , double startY, int dir,  int* pErrCode) ;

	virtual BOOL MoveArc(  double endX, double endY, double radius, BOOL bBigArc, int dir, int* pErrCode) ;
	virtual BOOL MoveCircle(  double centerX, double centerY, double startX , double startY, int dir,  int* pErrCode) ;

	virtual BOOL MoveArcXY2(  double endX, double endY, double radius, BOOL bBigArc, int dir, int* pErrCode) ;
	virtual BOOL MoveCircleXY2(  double centerX, double centerY, double startX , double startY, int dir,  int* pErrCode) ;

		
	virtual BOOL MoveArcXYZ(  double endX, double endY, double z, double radius, BOOL bBigArc, int dir, int* pErrCode) ;
	virtual BOOL MoveCircleXYZ(  double centerX, double centerY, double z, double startX , double startY, int dir,  int* pErrCode) ;

	virtual BOOL MoveArcXY2Z(  double endX, double endY,  double z, double radius, BOOL bBigArc, int dir, int* pErrCode) ;
	virtual BOOL MoveCircleXY2Z(  double centerX, double centerY,  double z, double startX , double startY, int dir,  int* pErrCode) ;


	//等待信号和动作完成
	virtual BOOL WaitAxis(int axis, BOOL bGoHome, int* pErrCode);
	virtual BOOL WaitBank(int bankId, int* pErrCode);
	


	//WaitInput受运动类的置反参数影响,该函数等待低电平
	//建议新应用不使用 该函数
	virtual BOOL WaitInput(int bit, int timeout, int* pErrCode);
	
	//WaitInput不受影响,可通过CGio反置点平 
	virtual BOOL WaitInput(CGio* pIn, int timeout, int* pErrCode);


	//等任意两轴 
	virtual BOOL WaitAny2(int axes, BOOL bGoHome, int* pErrCode) ;
	virtual BOOL WaitAny3(int axes, BOOL bGoHome, int* pErrCode) ;//任意3轴 

	virtual BOOL WaitAny4(int axes, BOOL bGoHome, int* pErrCode) ; //任意4轴回零

	//辅助	 
	BOOL CheckAxisReady(int act);
	BOOL DetermineScene(int act);

	//仅支持WD_ACT_RESET, WD_ACT_RESET_ZRXY, WD_ACT_RESET_ZXYY2
	BOOL   ResetAxes(int act, int* pErrCode);
	BOOL   HomeRaw (int axis, int* pErrCode);
	BOOL   RepeatMove( int* pErrCode);

	 

	//触发器
	//输入触发位， 初始电平，触发类型，触发周期(高低电平类型有效)
	BOOL RegisterTrigger(int bit, int initLevel, int type, int period);
	void UnregisterTrigger(int bit);


	//监视触发器状态
	BOOL ActivateTrigger();
	void DeactivavteTrigger();
	BOOL IsTriggerActive();

	//运动
	virtual CRobMot* Attach(CRobMot* pRobMot);
	CRobMot* GetRobMot();


public:
	HWND m_hNotifyWnd;
	
	
	
	//默认的运动参数
	//CWorkDesk根据scene调用GetMotionOpts获得运动参数
	CMotOpts m_homeOpts;  //回原点
	CMotOpts m_editOpts;  //编辑


	//临时变量
	//m_nPos 用于任意轴
	double m_nTx, m_nTy, m_nTy2, m_nTz, m_nPos ; //目标位置
	int    m_nCurAxis;
	BOOL   m_bMoveDirect;
	 
	//等待轴稳定时间,外部应用控制，减少逻辑耦合
	//int  m_nStillTime;
	
	
	 
//内部调用
public:
	BOOL ExcuteAction(int act);
	
	//触发器相关
	void CheckInputState(int* pExitCode);

	//子类重载该函数进行具体功能,该函数不要处理长时间任务，避免阻塞。
	//bit:输入位号, type: 触发类型,  bOn: 是否为发生触发状态
	virtual void   OnTriggerActivated(int bit, int type, int nLevel){;};

	//按照场景选择运动参数
	virtual CMotOpts* GetMotionOpts(int scene); 
	  
	 
//下面的函数会返回停止消息
//会发送消息	
protected:
	//下面halt函数如果发生错误，将设置ready为FALSE
	//单轴运动
	BOOL HaltSingleAxis(int axis, int mode, int* pErrCode);

	//插补停止
	//BOOL HaltMultiAxes(int axes, int mode, int* pErrCode);
	BOOL HaltAxis(int axis, BOOL bGoHome,int mode, int* pErrCode);

	//回零停止
	BOOL HaltHomeAxis(int axis, int mode, int* pErrCode);


	//三轴
	//计算下降连续段过渡点: 输入起点（p0），末点(p1)和百分比(0~1) ，计算水平段的过渡点（n0）和垂直段的过渡点(n1)
	void CalcFallingVertex(RvPoint3D_f64 p0, RvPoint3D_f64 p1, double delta, RvPoint3D_f64& n0, RvPoint3D_f64& n1 );

	//计算上升连续段过渡点: 输入起点（p0），末点(p1)和百分比(0~1)，计算水平段的过渡点（n0）和垂直段的过渡点(n1)
	void CalcRisingVertex(RvPoint3D_f64 p0, RvPoint3D_f64 p1, double delta, RvPoint3D_f64& n0, RvPoint3D_f64& n1);

	//计算上升到下降连续段过渡点: 输入起点（p0），末点(p1)，z轴高度和百分比(0~1)，计算水平段的过渡点（n0）和垂直段的过渡点(n1)
	void CalcArchVertex(RvPoint3D_f64 p0, RvPoint3D_f64 p1, double topZ, double delta, \
	                	RvPoint3D_f64& n0,  RvPoint3D_f64& n1, RvPoint3D_f64& n2,  RvPoint3D_f64& n3  );


	//两轴,　通常x,z轴
		
	//计算下降连续段过渡点: 输入起点（p0），末点(p1)和百分比(0~1) ，计算水平段的过渡点（n0）和垂直段的过渡点(n1)
	void CalcFallingVertexXZ(RvPoint_f64 p0, RvPoint_f64 p1, double delta, RvPoint_f64& n0, RvPoint_f64& n1 );

	//计算上升连续段过渡点: 输入起点（p0），末点(p1)和百分比(0~1)，计算水平段的过渡点（n0）和垂直段的过渡点(n1)
	void CalcRisingVertexXZ(RvPoint_f64 p0, RvPoint_f64 p1, double delta, RvPoint_f64& n0, RvPoint_f64& n1);

	//计算上升到下降连续段过渡点: 输入起点（p0），末点(p1)，z轴高度和百分比(0~1)，计算水平段的过渡点（n0）和垂直段的过渡点(n1)
	void CalcArchVertexXZ(RvPoint_f64 p0, RvPoint_f64 p1, double topZ, double delta, \
	                	RvPoint_f64& n0,  RvPoint_f64& n1, RvPoint_f64& n2,  RvPoint_f64& n3  );

	//*****start of @220430 
	//***以下函数为外部会零方式，控制不好做，删除，不再支持
	//
	//非常规回零方式。	
	//外部回零
	//BOOL   GoHomeE1(int axis, int reqBit, int reqLevel, int duration, int* pErrCode);
	//BOOL   WaitHomeE1(int axis, int ackBit, int ackLevel,   int* pErrCode);

	//单次回零,与卡无关,但需要调用卡的相关函数
	//BOOL GoHomeE2(int axis, int* pErrCode);
	//BOOL WaitHomeE2(int axis, int* pErrCode);
	//***************************end of @220430 
	
//public:
 //  void CaptureAndHomeE2();

protected:

	//运动执行类
	CRobMot* m_pRob;

   
	HANDLE m_hWorkThread;
	HANDLE m_hCheckThread;  //统一检测触发妻事件

	int  m_nCurScene;
	int  m_nCurState;
	int  m_nCurAct;
	BOOL m_bCanceled;
	int  m_nCurMode;

	//回零线程,以前外部回零。去掉，容易失控。
	//HANDLE  m_hHomeThreads[MAX_AXIS_COUNT];
	//int     m_nHomeStates[MAX_AXIS_COUNT];
	 

	//触发相关
	int           m_nTriggerCount;
	CSoftTrigger* m_pTriggerArray[WD_MAX_TRIGGER_COUNT];
	BOOL           m_bActiveTriggers;
};

