#pragma once
#include "MotorBase.h"

class CMotionControllerBase;
class CMotionController_ACS;
class AcsProgram;

class CMotor_ACS :
    public CMotorBase
{
public:
    CMotor_ACS(CMtrProfile mtrProfile, double *dpPos, CMotionControllerBase *pBaseController);
    virtual ~CMotor_ACS(void);
    void ConstructAxis() override;

    bool SendMsg(const std::string &msg);

//  method to On/Off motor
    bool OnMotor() override;
    bool OffMotor() override;

    bool IsMtrOn() override;
    bool GetMotorPosition(const CMtrProfile &mtrProfile, double *pRawPosition) override;
    BOOL IsNegLmtHit() override;
    BOOL IsPosLmtHit() override;
    BOOL IsHomed() override;
    BOOL IsMotorReady() override;
    BOOL IsMotorAlarm() override;
    BOOL HomeByIndex() override;
    BOOL HomeBySensor() override;
    void ProcessInt(int interrupt);

    void RunTask();
    void RunSend();

    bool DecelStop() override;
    bool EmergStop() override;
    bool GetMotorCommandedPosition(int nMtrNo, double *pRaw) override;
    int  GetMotionIOStatus(const CMtrProfile &mtrProfile) override;
    bool GetMotorPositionError(double *pRawPositionError) override;
    int  UpdateProfile() override;
    bool AbsoluteMove(double dPosition, int nMode, PROFILE_CURVE curve) override;
    bool RelativeMove(double dDistance, PROFILE_CURVE curve) override;
    bool SetMotorCommandedPosition(double dPosition) override;
    bool RefreshMotorConversionFactor() override;
    int  SetHomeMode(int iHomeMode) override;
    bool SetMotorPosition(double dPosition) override;
    void SetMotorProfile(double dValue, motion_profile::PROFILE_TYPE type) override;

    int GantryEnable(int nNoOfAxis, CMtrProfile *mtrProfile) override;
    int GantryDisable(int nNoOfAxis, CMtrProfile *mtrProfile) override;
    int SimultaneousMove(int nNoOfAxis, CMtrProfile *mtrProfile,  double *dPosition, double *dStartVel, double *dMaxVel, double *dAcc, int nMode = 0) override;
    int UpdateProfile(int iMtrNo, double dSpd, double dAcc, double dDec, double dJerk);
    int SegmentedMotion(int nAxis, const CMtrProfile *pMtrProfile, double *dPositions) override;
    int SegmentedLine(double *dPositions) override;
    int SegmentedEnd() override;
    int SegmentedArc(double *dCenter, double *dFinalPoint, int rotation) override;
    int MasterSlaveEnable(const CMtrProfile slaveMtrProfile, double offset, double leftBoundary, double rightBoundary) override;
    int MasterSlaveDisable(const CMtrProfile slaveMtrProfile) override;

    CString IntArrayToString(std::vector<int> vArray);
    CString DoubleArrayToString(std::vector<double> vArray);

    CString          IntArrayToString(int nItems, int *iArray);
    CString          DoubleArrayToString(int nItems, double *iArray);
    void             SetCallBackAxisMask(unsigned __int64 mask);
    unsigned __int64 GetCallBackAxisMask();
    void             StopCheckMotionEnd();

private:
    DWORD       WaitProgramDone(DWORD dwTimeout);
    int         SetGantryEnable(int nNoOfAxis, CMtrProfile *mtrProfile, int status);
    int         FindIndex(HOME_DIR homeDir, MOTION_SPEED speed);
    int         FindSensor(HOME_DIR homeDir, MOTION_SPEED speed);
    bool        ResetDriveError();
    bool        TestFault(int mask);
    bool        TestSafety(int mask);
    const char *GetErrorString();
    const char *GetErrorString(int errorNumber);
    bool        TestAcsResult(int line_nr, int result, char *code);
    bool                        m_bMotorEnabled;
    HANDLE                      m_hComm;
    char                        m_errorString[256];
    int                         m_lastError;
    bool                        m_bMotionError;
    CMotionController_ACS      *m_pAcsMotionController;
    CMotionLogger               m_logger;
    std::unique_ptr<AcsProgram> m_programBuffer;
    std::vector<int>            m_segmentedAxes;
    std::vector<CMtrProfile>    m_segmentedMtrProfile;
    unsigned __int64            m_axisMask;
    bool                        m_bMotionStarted;

    bool AnyMotionRequired(int nMtrNo, double position);
};
