//---------------------------------------------------------------------------

#ifndef ClientSessionFH
#define ClientSessionFH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include "PacketHandllingF.h"
#include "CDSCtlrF.h"
#include <winsock2.h>

typedef enum _rx_state
{
    RX_DLE,
    RX_STX,
    RX_DATA,
} RX_STATE;

typedef enum _e_session_state
{
    eSS_none,
    eSS_OnDisconnect,
    eSS_Disconnect,
    eSS_OnConnect,
    eSS_LoginReq,
    eSS_Connected,
    eSS_Recv,
} e_session_state;

struct RefCountable
{
	RefCountable()
	{
        FRefCount = 0;
    }
	virtual ~RefCountable(){}

	void IncRefCount() { ++FRefCount; }
	void DecRefCount() { --FRefCount; }
	int	 GetRefCount() { return FRefCount; }

	int FRefCount;
};
//---------------------------------------------------------------------------

class TClientSession;
struct OverlappedIO : public OVERLAPPED
{
	OverlappedIO()
    {
        FSession = NULL;
    }
	TClientSession *FSession;
} ;
//---------------------------------------------------------------------------

#define SERVER_MAX_PACKET_SIZE  8192       /* max packet size */
#define SESSION_RECV_BUFFER     (SERVER_MAX_PACKET_SIZE*100)
#define SESSION_SEND_BUFFER     (SERVER_MAX_PACKET_SIZE*100)

class TClientSession
{
public:
	TClientSession();
	TClientSession(SOCKET ASock, SOCKADDR_IN* ASockAddr);
	void Create(SOCKET ASock, SOCKADDR_IN* ASockAddr);
	virtual ~TClientSession();

private:
    e_session_state FState;
	bool			FConnected;
	SOCKET			FSocket;

	SOCKADDR_IN		FSocketAddr;
    AnsiString      FIpAddress;
    short           FPort;

    int             FPacketLen;
    int             FPacketSent;
    char           *FPacketPtr;
    char            FRecvBuff[SESSION_RECV_BUFFER];
    int             FRecvIdx;
    char            FSendBuff[SESSION_SEND_BUFFER];
    int             FSendIdx;

    BYTE            FMsgBuff[SESSION_SEND_BUFFER];

    TCDSCtlr       *FCDSCtlr;
    TCDSCtlr       *FCDSLogCtlr;
    AnsiString      FCtlrId;

    int         FLastErr;
    AnsiString  FErrorString;
    int         SocketError();
    void        Init();

public:
    int         FCloseTick;
    TDateTime   FTmrConn;
    TDateTime   FTmrSend;
    TDateTime   FTmrRecv;
    bool        FChkRecvTO;     // 수신 타임아웃 체크 플래그, true 이면 타임아웃 체크

    int   GetFreeSpaceSize();
    char* GetBuffer();
    void  RecvBuffCommit(int ARecvLen);

	bool OnConnect();
	void Disconnect();
    bool OnDisconnected();               /* PacketHandllingF.cpp */

	bool SendPacketDleStuffing(char *AData, int ADataLen);
	bool SendPacketDLE(char *AData, int ADataLen);
	bool SendPacket(char *AData, int ADataLen);
	bool SendRequest(char *AData, int ADataLen);
	bool SendFlush();
    bool SendFlushComplete();
	void OnWriteComplete(int ASendLen, int AReqLen);

    void OnWrite(char *APktPtr, int ASendLen);  /* PacketHandllingF.cpp */
	void OnRead(int ALen);                      /* PacketHandllingF.cpp */
    bool CheckLoginClient();                    /* PacketHandllingF.cpp */
    bool InfoPacket(BYTE AOpCode, int ALen, bool ASend, int AResult=0);

	template <class PKT_TYPE>
	bool ParsePacket(PKT_TYPE& pkt, int APktLen);

	char* GetPacket();
	bool  ResetPacket(int APktLen);

    int ReqStauts();
    int ReqPowerModuleStatus();
    int ReqDisplayModuelStatus();

    int ReqParameter();
    int ReqPixelImage(char *ACmd);
    int ReqUploadCurrentForm();
    int ReqDisplayDefaultForm();
    int ReqUploadScheduleForm();
    int ReqDisplayFormId(char *ACmd);
    int ReqStatusControl(char *ACmd, int ALen);
    int ReqSendPacket(char *ACmd, int ALen);

    int download_form_schedule(bool ASchedule=true);
    int download_form_schedule_complete();
    int download_default_form_0x9A();
    int download_form_0x9A();
    int download_file_0x82();
    int download_schedule_form_0x96();
    int download_blank_0x9E();

    //문자식
    int download_lib_form_0x0A();
    int download_schedule_form_0x0E();
    int download_blank_0x16();

    void DisplayResponseError(BYTE *AData);

#if 0
    int ReqLedPowerControl(BYTE AOnOff);
    int ReqFanPowerControl(BYTE AOnOff);
    int ReqTimeControl(char *ATime);
    int ReqBrightSet(char *ACmd);
    int ReqConfigSet(char *ACmd);
    int ReqReset(int AMode);
#endif
    char* GetRecvBuff() { return FRecvBuff; }

    int LogData(char *ASndRcv, BYTE *AData, int ALen);
    int LogWrite(int ALogKind, char *AFmt, ...);
    int SysLogWrite(int ALogKind, char *AFmt, ...);

public:
    __property bool            IsConnected  = { read = FConnected };
    __property SOCKET          Socket       = { read = FSocket };
    __property e_session_state State        = { read = FState, write = FState };
    __property AnsiString      IpAddress    = { read = FIpAddress, write = FIpAddress };
    __property short           Port         = { read = FPort, write = FPort };
    __property TCDSCtlr*       CDSCtlr      = { read = FCDSCtlr, write = FCDSCtlr };
    __property TCDSCtlr*       CDSLogCtlr   = { read = FCDSLogCtlr, write = FCDSLogCtlr };
    __property AnsiString      CtlrId       = { read = FCtlrId, write = FCtlrId };

};
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
void CALLBACK RecvCompletion(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags);
//void CALLBACK SendCompletion(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags);
//---------------------------------------------------------------------------

#endif
