#ifndef CMALLSYSTEM_H
#define CMALLSYSTEM_H

#include "RecordLog.h"
#include "RecordProductLog.h"
#include "v_msgqueue.h"
#include "ccassette.h"
#include "cimagecontainer.h"
#include <QTranslator>
#include <QReadWriteLock>
#include "export_logic.h"
#include "csystem_external.h"

class CMAllsystem : public CSystemExternal
{
public:
    enum AllSystem_State_ID
    {
        SIMULATE,
        OFF_LINE,
        ON_LINE,
    };
    CMAllsystem();
    virtual ~CMAllsystem();
    int32_t createSystem();
    void createWorker(int istate);
    void createCam(int istate);
    void createCassette(int istate);
    void createLaser(int istate);
    void createLaserPath(int istate);
    void createLight(int istate);
    void createMotor(int istate);
    void createProduct(int istate);
    void createStatemachine(int istate);
    void createWorktable(int istate);
    void createPowerMeter(int istate);
    void createSide(int istate);

    void createOffset(int istate);
    void createBarcode(int istate);
    void createCoatVolumeSensor(int istate);

    void createHgripper(int istate);
    void createGEM(int istate);
    void createMeasureDistance(int istate);
    void EMO();
    void LEAVE_EMO();

    void prepareSystem();
    void exitSystem();

    bool IsDebug() override;

    bool IsSimulator() override;

    void AssertCheckWtVaccum() override;
    /*!
     * 执行手动操作，只检查当前状态机不在自动或半自动状态
     *
     * \param iSMID
     * \param msgqueue
     * \param bReport
     * \return
     */
    bool start_manual(int iSMID, const V_MsgQueue& msgqueue,
                      bool bReport = true) override;
    /*!
     * 执行半自动操作
     * 需要状态机不在工作暂停状态才能执行操作
     * Idle或者SemiWait状态
     * \param iSMID
     * \param msgqueue
     * \param bReport
     * \return
     */
    bool start_semi(int iSMID, const V_MsgQueue& msgqueue,
                    bool bReport = true);
    /*!
     * 执行与传片相关联的手动操作，传片不能启动
     *
     * \param iSMID
     * \param msgqueue
     * \param bReport
     */
    void start_test(int iSMID, const V_MsgQueue& msgqueue,
                    bool bReport = true) override;

    void start_reset(int iSMID, const V_MsgQueue& msgqueue, bool bReport = true);
    void abort_state(int iSMID, int iStateID, QVariantList& extraData, bool bOnnlyCurMachine = false) override;
    void absmove_xy(double dx, double dy) override;

    void absmove_xy_msg(double dx, double dy, V_MsgQueue& msgqueue) override;
    void relmove_xy_msg(double dx, double dy, V_MsgQueue& msgqueue) override;
    void absmove_msg(double dpos, int ichID, V_MsgQueue& msgqueue) override;
    void relmove_msg(double ddis, int ichID, V_MsgQueue& msgqueue) override;
    void jogmove_msg(double dSpd, int ichID, V_MsgQueue& msgqueue);
    void stopmove_msg(int ichID, V_MsgQueue& msgqueue);
    int32_t m_iCellSize;

    void changeChannel_msg(int32_t idestCh, bool bmove, V_MsgQueue& msgqueue) override;
    void changeChannel(int32_t idestCh, bool bmove) override;

    void changeSide_msg(int32_t iside, bool bxymove, V_MsgQueue& msgqueue) override;
    void ChangeSide(int iSideID);

    int CheckWtPos(const CMPointd& pt);

    void WriteRecipe(ConfigStreamWriter& streamWriter, int iVersion) override;

public:
    void* m_pMWCamLight2X;
    void* m_pMWCamLight6X;
#ifdef __USE_THIRD_CAMERA__
    void* m_pMWCamLight4X;
#endif

    void SetCamParam(int iCamId, int exposureUs, int gain) override;
    void SetCamParam_sig(int iCamID, int exposureUs, int gain, V_MsgQueue& msgqueue);

    void SetCamLight(int32_t iCamID, int32_t light, bool bdirect,
                     bool bsetDefault) override;
    void SetCamLight_sig(int32_t iCamID, int32_t light, bool bdirect,
                         bool bsetDefault, V_MsgQueue& msgqueue);



    void SetDefaultLight(int32_t iCamID);
    void SetDefaultLight_Sig(int32_t iCamID, V_MsgQueue& msgqueue);

    int32_t get_lightdata(int32_t iCamID, bool bdirect);
    void write_config(bool bAll);
    void read_config(bool bAll);

    void write_wafersize_config();
    void read_wafersize_config();

    int read_language_config();

    void Serialize(QDataStream& stream, bool bwrite);
    virtual void ReadRecipe(ConfigStreamReader& streamReader, int iVersion) override;

    virtual void EvtLog(QString& evt, QString& data) override;
public:

    /**
     * @brief X方向加工.
     *
     * @param dStartPosX
     * @param dEndPosX
     * @param dPosY
     * @param dPosZ
     * @param iDelayTime
     * @param iLaserPathID
     * @param dOffsetY 定位偏移补偿
     * @param dspd  加工速度
     * @param iSide SIDE
     * @param iSubIndex 子加工线
     * @param bEnableLaser 是否启用激光
     * @param bSetIOStatus 设置激光状态，灯及吹气
     * @param dAccSpeed 加工加速度
     * @param bSetCutSpeed 是否设置默认速度，默认都需要设置，为节约时间，有时候是在一组之前设置
     * @param bCloseLaserIO 结束后，执行一次关激光IO的操作
     */
    int CutPosX(double dStartPosX, double dEndPosX, double dPosY, double dPosZ,
                int iDelayTime, int iLaserPathID, double dOffsetY,
                double dspd, int iSide, int iSubIndex, bool bEnableLaser, double dAccSpeed = 0,
                bool bSetIOStatus = true, bool bSetCutSpeed = true, bool bCloseLaserIO = true) override;
    int CutPosY(double dStartPosY, double dEndPosY, double dPosX, double dPosZ,
                int iLaserPathID, double dOffsetX, double dOvercut,
                double dCutSpeed, double dAccSpeed);


    int CutPos(double dStartPos, double dEndPos, double dLocationPos, double dPosZ,
               double dOffsetPos, double dOverCut,
               int iLaserPathID, bool bXDirect,
               double dCutSpeed, double dAccSpeed, bool bEnableLaser) override;

    bool CalcPos(double dStartPos, double dEndPos, double dLocationPos, double dPosZ,
                 double dOffsetY, double dOverCut,
                 int iLaserPathID, bool bXDirect,
                 double dCutSpeed, double dAccSpeed,
                 CMPointd& axisStart, CMPointd& axisEnd, double& dGatePosStart, double& dGatePosEnd);

    //bool CalcPos(double dStartPosX, double dEndPosX, double dPosY, double dPosZ,
    //             double dOffsetY, double dspd, int iLaserPathID,
    //             CMPointd& AxisStart, CMPointd& AxisEnd, CMPointd& AxisGateStart, CMPointd& AxisGateEnd);


public:
    void VacuumSet(bool bOn, int IOOutput, int IOInput = -1);
    void VaccumBreak(int IOOutput);

    bool IsVaccumOn(int IOOutput, int IOInput);
    void VacuumLeakCheck(int IOOutput, int IOInput);

    bool CellExist(int IOOutput, int IOInput) override;

    void MainPressCheck();
    void SafeDoorCheck();
    void CloseSafeDoor();
    void OpenSafeDoor();
    bool IsSafeDoorOpened();
public:
    void SetIndicatorLight(Qt::GlobalColor color, bool bon);
    void SetIndicatorBuzz(bool bon);
    DWORD GetIndicatorLight();
public:
    bool m_bCamMove;
public:
    bool m_bEnableCycle;	//循环跑
    bool m_bOnlyLeveling;   //仅调平
    bool m_bOnlyLocation;   //仅定位
    bool m_bOnlyASide;
    bool m_bOnlyBSide;
    bool m_bPausedAfterLocation; //Location完成后暂停
    bool m_bPausedAfterLeveling; //定位完成后暂停
    //bool m_bDisableCutlineLaser; //是否禁用自动划线时出激光
    
    bool m_bScanTwoSensor;
    bool m_bSimulatorLeveling;
    bool m_bSimulatorLocation;
    double m_LaserGateDelay;
    double m_LaserGateDelayEnd;
    bool m_bAllSMStoped;
    int m_iAsideStart;
    int m_iAsideEnd;
    int m_iBsideStart;
    int m_iBsideEnd;
    int m_iCoatPreSpayWaitTimeMs;
    bool m_bStopAfterFinish;
    //bool m_bEnbaleLaserOpen;
    QString m_strserialID;
    CRecordLog m_recordLog;
    CRecordProductLog m_productLog;

    CARDSMAP m_RecipeCards;
    SMMAP m_RecipeSMS;
public:
    virtual void Reset_All_Side(bool bRsetCutLine = true);

    int m_iMatchType;
public:
    QString makeModelPath(QString& fileName, int32_t iSideid, int32_t iCamid);

    void  SetCutStreet(CImageContainer* pContainer, int iSideID, int iCamID, bool bSetBoth = false) override;
public:

    //int32_t m_iCurChID; //当前通道 相机
    //int32_t m_iCurSideID;//当前面 A面 B面
    int32_t m_iCurProcessID; //当前执行操作的Process
    int32_t m_iCurLine; //当前切割道
    //int32_t m_iCurLayer;    //当前切割的第几层
    CPreciseTime m_lineTime;
    CPreciseTime m_cellTime;	//总加工时间
    CPreciseTime m_totalCoatTime;	//涂敷时间
    CPreciseTime m_totalCleanTime;	//清洗时间
    CPreciseTime m_fullAutoTime;
    //总工作时间，包括暂停的时间
    CPreciseTime m_totalWorkTime;
    double m_totalWorkHour;
    //总切割的时间
    int32_t m_iTotalCuttedWafer;
public:
    bool IsAllSMStopped();
    bool IsAllSMIdle();
    bool IsSMStopped(int smID);
    bool IsSMIdle(int smID);
    bool IsSMAutoPaused(int smID);
    bool IsSMAutoRun(int smID) override;
    bool IsSMAutoMode(int smID);
    bool StopSemi(int smID);
    void LogInfo(const QString& msg, const char* pFile = "unkown", int line = 0) override;
    void LogError(const QString& msg) override;
    void AddProductInfo(CASSSLOT* pSlot, const QString& info, bool toLog = true);
    void AddProductInfo(const QString& waferId, const QString& info, bool toLog = true);
    void AddProductInfo(int processId, const QString& info, bool toLog = true) override;
public:
    /**
     * 准备回原的操作.
     *
     * \param iMotorID
     */
    void OnPrepareHome(int iMotorID);
    /**
     * 回原完成的操作.
     *
     * \param iMotorID
     */
    void OnAfterHome(int iMotorID);

    /**
     * 外部限位检查.
     *
     * \param motorId
     * \param targetPos
     */
    void OnLimitCheck(int32_t motorId, double targetPos);


    /*!
     * 检查轴是否可以运动
     *
     * \param iMotorID  轴ID
     * \param checklimit 检查是否在限位上，默认false
     * \param idirect   运动方向1为正向
     * \param dTargetPos    目标位置
     * \param bIsHoming 是否是在回原过程中
     */
    void OnIsMotorMoveAvailable(int iMotorID, bool checklimit = false, int idirect = 1,
                                double dTargetPos = 0, bool bIsHoming = false);
    /**
     * 检查IO是否可以控制.
     *
     * \param iIOID IO ID
     * \param bSet true为触发
     */
    void OnIsIOSetAvailable(int32_t iIOID, int32_t bSet);

    void OnFireOn(int32_t iLaserId, bool bOpen);
    void CheckLimitAndHoming(int iMotorID, bool bChecklimit, int idirect, bool bIsHoming);
    bool CheckAutoStart(QString& msg, bool bAsk);
    void publish_msg(const V_Msg& msg);
    bool IsAutoMode();
    void GetSaveDoorCtrl(bool& bLeft, bool& bRight);
    bool IsAcsInited();

public:
    bool m_bMoveInitPos;
    QTranslator m_appTranslater;
    void SetLotId(const QString& lotId);
    void SetWaferId(int processId, const QString& waferId);
    void SetWaferId(int processId, CASSSLOT* pSlot);
    void SetWaferIdEmpty(int processId);
    QString MakeRecoverPath(const QString& file) override;
    bool WriteRecoverData();
    bool ReadRecoverData(QString& recipeName, QString& slotNo);

    std::string GetTransWaferId();
    std::string GetMainWaferId();
    std::string GetCoatWaferId();
    std::string GetCleanWaferId();
    std::string GetLotId();
public:
    void SendLogMessage(const QString& info, int type) override;
    void SendTerminalMessage(const std::string& info);

    bool SendEvent(_EventID eventID) override;
    bool SetVariable(_SVID svid, const std::string newValue) override;
public:
    std::function<void(const QString& info, int type)> m_pfnNotifyLogMessage = nullptr;
    std::function<void(const std::string& info)>m_pfnNotifyTerminalMessage = nullptr;

private:
    void initNameList();
    QReadWriteLock m_mutexWaferId;
    std::string m_sLotID;
    std::string m_sTransWafterId;
    std::string m_sMainWaferId;
    std::string m_sCoatWaferId;
    std::string m_sCleanWaferId;
    bool m_bIsSimulator;
};

class CMSystemHelper
{
public:
    CMAllsystem& GetSysInstance();
    void SetInstance(CMAllsystem* pInstance);
    static CMSystemHelper& Instance();

private:
    CMAllsystem* m_pInstance = nullptr;
};


#define m_gSystem CMSystemHelper::Instance().GetSysInstance()
//#define GET_CHANNEL(c,d,t) (dynamic_cast<t*>(m_gSystem.mcards[d]->mchannels[c]))
//#define GET_CHDIRECT(c,t) (dynamic_cast<t*>(m_gSystem.FindChannel(c)))
//#define GET_CARD(d,t) (dynamic_cast<t*>(m_gSystem.FindCard(d)))
//#define GET_STATEMACHINE(m,t) (dynamic_cast<t*>(m_gSystem.FindSM(m)))
//#define GET_PROCESS(p,m,t) (dynamic_cast<t*>(m_gSystem.msms[m]->FindProcess(p)))
//#define GET_PRSDIRECT(p,t) (dynamic_cast<t*>(m_gSystem.FineProcess(p)))
//#define GET_STATE(s,m,t)(dynamic_cast<t*>(m_gSystem.msms[m]->mstates[s]))


#endif // CMALLSYSTEM_H

