#pragma once

#include <string>

#include "ISGManager.h"
#include "BufferedSocket.h"
#include "SGLogger.h"

#define MAXSOCKBUF        4096
#define SG_END_TERMINATOR '\n'

// SGManager.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CSGManager document

/*************************************************************************************/
class ISGManagerObserver;
class CSGManager : public ISGManager, IBufferSocketCallBack
{
public:
    CSGManager();
    virtual ~CSGManager();

    void EnableEventForAllMode();
    void DisableEventForAllMode(); // Note: Event Enable in PRODUCTION Mode
    std::string GetControlState();
    std::string GetLinkState();
    bool IsOnlineRemote();
    bool IsEnableCommunicating();
    bool IsOnlineLocal();
    bool IsSpoolActive();
    bool IsConnectWithSecsGem(); // check for connection between handler and Ti secs gem
    bool m_bDataComplete;
    std::string m_RcvBuff;
    void OnReceive(const char* buf, int size);
    void OnDisconnect(int errorCode);
    void ResetReceiveBuffer();
    /**********************************************************************/
    //  LPTSTR psMsg;
protected:
    /******************************* To Hanlder info ***********************/
    std::string m_strSecsGemConnection;
    std::string m_sSGMainMode;
    std::string m_sSGLoginUser;
    std::string m_sMachineState;
    bool m_bIsSecsGemEnabled;
    HWND m_hHandler;

    PROCESS_INFORMATION g_pi;
    /**********************************************************************/
    /**********************************************************************/
    int m_NumberOfDay;
    /**********************************************************************/
public:
    /************** Handler Calling Functions *****************************/
    bool ConnectSocketSecsGem(bool bUpdateParameter = true); // To make connection with Independent Secs/Gem
    bool DisconnectSocketSecsGem();                          // To disconnect Secs/Gem application

    // Secsgem Application Function
    void SetEnableLogFile(bool bEnable = true);
    void SetLogLevel(std::string level);
    void SetNumberOfDaysKeepInMemoryForLogFile(int nDays = 30);
    bool SetSecsGemIpAddressAndPort(ISGManagerObserver* pObserver, int iPort, const char* pStrIpAddress, bool bConnect = false, bool bUpdateParameter = true);
    bool StartAndConnectSecsGemApplication(ISGManagerObserver* pObserver); // To Start Secs/Gem application and connect
    bool CloseSecsGemApplication();                                        // To close secsgem application
    bool StartSecsGemApplication();                                        // To start Secsgem application

    // SecsGem Status Function
    bool GoOnLine();                                 // To switch to SecsGem Online mode
    bool GoOffline();                                // To switch to SecsGem Offline mode
    bool GoRemote();                                 // To switch to Online/Remote control state
    bool GoLocal();                                  // To switch to Online/Local control state
    bool SecsGemDisableLink();                       // To disable SecsGem Link
    bool SecsGemEnableLink() override;               // To enable Secsgem Link
    bool SetMainMode(std::string sMode);             // To set Main Mode
    bool SetUserLevel(std::string sUserLevel);       // To set User level
    bool SetProcessState(std::string sProcessState); // To set process state
    bool UpdateCurrentParameters();                  // To send current mainmode, user and process state to secsgem appln

    // Send Event Function
    bool SendEvent(unsigned int iEventID); // To send Event,iEventReply:0= No need to Watit Event Reply

    // Update Variable Function
    bool SetVariableValue(UINT iVariableID, UINT iFormat, int iValue);         // To set  Integer Variable value
    bool SetVariableValue(UINT iVariableID, UINT iFormat, long iValue);        // To set Long variable value
    bool SetVariableValue(UINT iVariableID, UINT iFormat, std::string iValue); // To set string variable value
    bool SetVariableValue(UINT iVariableID, UINT iFormat, double iValue);      // To set floating point variable value

    // Alarm Function
    bool SendAlarmOn(UINT iAlarmID, std::string sAlarmText);  // To send Alarm On
    bool SendAlarmOff(UINT iAlarmID, std::string sAlarmText); // To send Alarm Off
    bool ClearAllAlarms();                                    // To clear all alarms

    // Data Set Function
    bool UploadData(std::string strName);   // To Upload Data
    bool DownloadData(std::string strName); // To download data
    bool ResetData();                       // To reset data

    // Wafer map Function
    bool DownloadWaferMap(std::string sWMapID, int nType = 2, int nFormat = 1, int nFNLoc = 0, int nRotAngle = 0, int nOrgLoc = 0, std::string strBinCodeEq = "", std::string strNullBinCodeEq = "");
    bool UploadWaferMap(std::string strName);   // To Upload Wafer Map
    bool DownloadStripMap(std::string strName); // To download strip Map

    bool DisplayTerminalMsgDialog();                                    // To display terminal message
    bool AcknowledgeRemoteCommand(std::string sRmtCmd, int iReturnVal); // To acknowledge remote command

    // Process Program Management(Recipe)
    bool DownloadRecipe(std::string strName); // To download recipe
    bool UploadRecipe(std::string strName);   // To Upload recipe
    bool UpdateRecipeList();                  // To update recipe list

    // ***************************************************************
    // Verify recipe after download recipe, then send S7F27 for PASS or FAIL
    // strResultData = "PASS": successful load recipe
    // strResultData = "FAIL": Fail to load recipe
    // Note:Do not use this function unless customer request
    // ***************************************************************
    bool SendRecipeVerification(std::string strResultData); // reply to host

    // ***************************************************************
    // To Add Recipe
    // bRefreshRecipe = true  :Not Send GemPPChangeEvent to host
    // bRefreshRecipe = false :Send GemPPChangeEvent with PPCHANGESTATUS(Created) to host
    // ***************************************************************
    bool AddRecipe(std::string strName, bool bRefreshRecipe = false);

    // ***************************************************************
    //  After delete Recipe file at C:\\PPDER and D:\\PPDER,
    //  then send GemPPChangeEvent with PPCHANGESTATUS(Deleted) to host.
    // ****************************************************************
    bool DeleteRecipe(std::string strName); // To delete Recipe

    // ***************************************************************
    // bRefreshRecipe = true  :Delete all recipe at C:\\PPDIR only
    // bRefreshRecipe = false :Delete all recipe at C:\\PPDIR and D:\\PPDIR
    // ***************************************************************
    bool DeleteAllRecipe(bool bRefreshRecipe = false);

    // ***************************************************************
    //  Send GemPPChangeEvent with PPCHANGESTATUS(Changed) to host.
    //  After edit recipe, need to call this function to inform to host.
    // ****************************************************************
    bool EditRecipe(std::string strName);

    // ***************************************************************
    //  Send EPT Module Data to host.
    // ****************************************************************
    bool SendEPTData(int nModuleID, std::string strTaskName, int nTaskType, int nEPTState, int nBlockedReson, std::string strBlockedReasonText);

public:
    void OnReceivedControlState(std::string m_sControlState);                           // This function is called when Control State change is received
    void OnReceivedLinkState(std::string m_sLinkState);                                 // This function is called when Link State change is received
    void OnReceivedSpoolState(std::string m_sSpoolState);                               // This function is called when Spool State change is received
    void OnWaferMapDownloaded(std::string m_sWaferMapDownloaded);                       // This function is called when Wafer Map downloaded
    void OnStripMapDownloaded(std::string m_sStripMapDownloaded);                       // This function is called when Strip Map downloaded
    void OnWaferMapUploaded(std::string m_sWaferMapUploaded);                           // This function is called when Wafer Map Uploaded
    void OnRecipeDownloaded(std::string m_sRecipeDownloaded);                           // This function is called when Recipe is downloaded from Host
    void OnRecipeUploaded(std::string m_sRecipeUploaded);                               // This function is called when Recipe is uploaded.
    void OnRecipeDeleted(std::string m_sRecipeDeleted);                                 // This function is called when Recipe is deleted.
    void OnRecipeAdded(std::string m_sAddedRecipe);                                     // This function is called when Recipe is added
    void OnDatasetUploaded(std::string m_sDatasetUploaded);                             // This function is called when Data Set uploaded
    void OnDatasetDownloaded(std::string m_sDatasetDownloaded);                         // This function is called when Dataset downloaded from Host
    void OnRemoteCommandReceived(std::string m_sRemoteCmdReceived, int nReply = 0);     // This function is called when a Remote command is received
    void OnRecipeUpdateNumberOfRecipe(std::string m_sNumberOfRecipe);                   // This function is called when Number recipe received
    void OnRecipeUpdateNthRecipe(unsigned int iRecipeNumber, std::string m_sNthRecipe); // This function is called to updated Nth Recipe
    void OnRecipeUpdatedList();                                                         // This function is called when updated Recipe List.
    void OnReceivedPendingMessage(std::string m_sPendingReadMsg);                       // This function is called whenever message received
    void OnReceivedE10State(std::string m_sE10State);                                   // This function is called when E10 State change is received

    void SetSecsGemDataFileFolder(std::string m_sSGDataFileFolder); // Write secs gem data to this file
    void OnAllRecipeDeleted(std::string m_sRecipeDeleted);
    void OnRecipeEdited(std::string m_sRecipeEdited);
    void OnECChanged(std::string sECID, std::string sECData); // Thi function is call when host change ECID value.
    bool SendMsgToSecsGem(std::string pStr);
    void SetWinHandler(HWND hHandler);

    void NotifyHandlerToConnect();

protected:
    virtual void NotifyHandler(WPARAM wParam, LPARAM lParam);

private:
    /************************** private fields **************************/
    int m_nSGPort;
    char m_szSGIpAddress[128];
    ISGManagerObserver* m_pObserver;
    /******************************* To Hanlder Info ***********************/
    int m_iEnableForAllMode;
    std::string m_sControlState;
    std::string m_sLinkState;
    std::string m_sSpoolState;
    std::string m_sWaferMapDownloaded;
    std::string m_sStripMapDownloaded;
    std::string m_sWaferMapUploaded;
    std::string m_sRecipeDownloaded;
    std::string m_sRecipeUploaded;
    std::string m_sRecipeDeleted;
    std::string m_sAddedRecipe;
    std::string m_sDatasetUploaded;
    std::string m_sDatasetDownloaded;
    std::string m_sRemoteCmdReceived;
    std::string m_sNumberOfRecipe;
    std::string m_sNthRecipe;
    std::string m_sE10State;
    std::string m_sGeneralCmdReceived;

    unsigned int iRecipeNumber;

    std::string m_sPendingReadMsg;
    std::string m_sSecsGemDataFile;
    CSGLogger logger;

private:
    /************************** private methods *************************/
    bool static SkipToNextData(char** ppStr);
    std::string GetNextData(char** ppStr);
    CBufferedSocket* m_pSocketSecsGem;
};
