// OutputController.h: interface for the COutputController class.
//
//////////////////////////////////////////////////////////////////////
#pragma once

#include <array>
#include <map>
#include <vector>

#include "HardwareIni.h"
#include "OutputControllerBase.h"

#ifdef BUILD_IODLL
#define IODLLCLASS __declspec(dllexport)
#else
#define IODLLCLASS __declspec(dllimport)
#endif

class COutputSetting;

class IODLLCLASS COpStatus
{
public:
    char m_cPtName[100];
    bool m_bOn;
    bool m_bRequestChgState;
    bool m_bChgStateOn;
};

class IODLLCLASS COutputController : public CCard
{
public:
    friend UINT OutputControllerThreadFn(LPVOID pParam);

    COutputController();
    virtual ~COutputController();

    BOOL SetVoltage(const COutputSetting& OutputSetting, double dVoltage, double dRange);
    BOOL Off(const COutputSetting& OutputSetting);
    BOOL IsOn(const COutputSetting& OutputSetting);
    BOOL On(const COutputSetting& OutputSetting);
    BOOL InitController(void);

    //  return the size of gOutputArray
    int GetSizeofOutputArray();

    //  make a copy of gOutputArray
    void CopyOutputStatus();
    //  void CopyOutputArray(BOOL bOutputArray[]);

    //  check if there is state change in output
    BOOL IsOutputStateChange(int iOutputNo, BOOL& bOutputState);
    //  BOOL IsOutputStateChange(BOOL bOutputState,int iOutputNo);

    //  allocate array size for output array
    void InitOutputArray();

    //  copy of gOutputArray that is used to compare the output state during machine running vs
    //  output state in maintenance mode
    std::vector<BOOL> m_vecOutputArray;

    //  to keep track output state array size
    int m_iOutputStateArraySize{ 0 };

    CMutex m_OutputMutex;

    static COutputController* GetInstance();
    COutputControllerBase* GetController(int nCardType);

    void StartUpdateThread();

    void TerminateThread();

    void StartUpdate(bool bStartUpdate);

    void SetSimulationIO(const std::vector<std::string>& vecSimulationIO)
    {
        m_vecSimulationIO = vecSimulationIO;
    }

    const std::vector<std::string>& GetSimulationIO()
    {
        return m_vecSimulationIO;
    }

private:
    std::array<COutputControllerBase*, MAX_OUTPUT_CARD_TYPE> m_outputControllerBase{};

    int m_nNoOfCardType{ 0 };
    CHardwareIni m_iniHardware;
    std::vector<stCard> m_vecCard;

    std::vector<std::string>  m_vecSimulationIO;

    static COutputController* instance;

    CWinThread* m_pThread{ nullptr };

    CEvt m_evtTerminate;
    CEvt m_evtStartUpdate{ "OUTPUT CONTROLLER START UPDATE" };
};
