// GPVision.h: interface for the CGPVision class.
//
//////////////////////////////////////////////////////////////////////

#pragma once

#include <vector>
#include <string>

#include "VisionNW.h"
#include "Utility.h"

#ifdef BUILD_COMMDLL
#define COMMDLL_DLLCLASS __declspec(dllexport)
#else
#define COMMDLL_DLLCLASS __declspec(dllimport)
#endif

#define END_TERMINATOR '\r'

constexpr size_t MAX_VISION_STATION = 20;

enum NEXT_SOT
{
    REF_AUTO_CALIBRATION = 2,
    RESOLUTION_AUTO_CALIBRATION,
    MANUAL_TEACH,
    INSPECTION,
};

enum TYPE_ID
{
    TYPE1 = 1,
    TYPE2,
    TYPE3,
    TYPE4,
    TYPE5,
    TYPE6,
    TYPE7,
};

struct stGPDoubleDataResult
{
    double dResult1;
    double dResult2;
    double dResult3;
    double dResult4;
};

class CScanner;

class COMMDLL_DLLCLASS CGPVision : public CVisionNW
{
public:
    CGPVision(std::string csMutexName = _T("gp_vision_mutex"), size_t nMaxStation = MAX_VISION_STATION);
    virtual ~CGPVision();

    // feature to enable/disable multiple app display. Used along with SwitchAppWindow
    bool MultipleAppWindow(bool bEnable, DWORD dwTimeout = 5000);

    bool SwitchAppWindow(int nStationNo, DWORD dwTimeout = 5000);
    bool IsLotOpen();
    bool WaitInTeach(int nStationNo, DWORD dwTimeout);
    bool WaitResultReady(int nStationNo, DWORD dwTimeout);
    bool WaitImageTaken(int nStationNo, DWORD dwTimeout);
    bool CameraLiveCapture(int nStationNo, bool bOn = true);
    bool IsTeachingValid(int nStationNo, int nTypeID);
    bool GetResult(int nStationNo, std::string& csResult);
    std::string GetReceiveData();
    bool Send(std::string csMsg);
    bool IsConnectedToServer();
    void Disconnect();
    bool Connect(int nPortNo, std::string csIPAddress, bool bServer = true);
    // static void StaticReceiveComm(const char *cpcBuffer, int nSize);
    void StaticReceiveComm(const char* cpcBuffer, int nSize);
    bool SetShiftID(std::string csShiftID);
    bool SetNetUPH(long lNetUPH);
    bool SetGrossUPH(long lGrossUPH);
    bool SetMachineName(std::string csName);
    bool SetOperatorID(std::string csOperatorID);
    bool SetLotSize(long lLotSize);
    bool IsTeach(int nStationNo);
    bool IsRun();
    bool IsAck();
    bool Stop();
    bool Run();
    bool DataEnd();
    bool DataStart();
    bool SetLotNumber(std::string csLotNumber);
    bool SetPackageID(long lPackageID);
    bool GetResult(int nStationNo, stGPDoubleDataResult& st_dResult);
    bool CheckResultReady(int nStationNo);
    bool CloseLot();
    bool OpenLot(int nPackageID, DWORD dwTimeout = 5000);
    bool CheckImageTaken(int nStationNo);
    bool StartInspect(int nStationNo, int nNextSOT = 0, int nTypeID = 0);

    virtual void ReceiveComm(const char* cpcBuffer, int nSize);

    HANDLE GetResultReadyHandle(int nStationNo);
    HANDLE GetImageTakenHandle(int nStationNo);

    // private:
protected:
    bool SendCommand(std::string csCommand, bool bWaitAck = false, DWORD dwTimeout = 5000);
    bool GetStatus();
    bool SendMsg(std::string csMsg, DWORD dwTimeout, bool bWaitAck = false);

    CMutex m_GPVisionMutex;
    
    size_t m_nMaxStation{ MAX_VISION_STATION };
    HANDLE m_hAck;
    HANDLE m_hStatusReady;

    std::vector<HANDLE> m_hImageTaken;
    std::vector<HANDLE> m_hInTeach;
    std::vector<HANDLE> m_hResultReady;
    std::vector<HANDLE> m_hTeachValidReady;

    std::vector<stGPDoubleDataResult> m_stResult;
    std::vector<std::string> m_vecResult;

    bool m_bRunMode;
    char m_cReceiveData[MAXSOCKBUF];
    bool m_bTeachingValid;
    bool m_bLotOpened;
    char m_cRcvData[MAXSOCKBUF];

    static bool m_bInitBefore;
};
