#include <stdio.h>
#include "App_Client.h"
//---------------------------------------------------------------------------
TClient	*clClient[MAX_CONNECTION];

//---------------------------------------------------------------------------
// 생성자
//---------------------------------------------------------------------------
TClient::TClient() : TThread(false)
{
	Priority 	= tpTimeCritical;

	Context		= new TIdTCPClient(NULL);
}

//---------------------------------------------------------------------------
// 소멸자
//---------------------------------------------------------------------------
__fastcall TClient::~TClient()
{
	Terminate();

	delete Context;
}

//---------------------------------------------------------------------------
// 접속 중인가?
//---------------------------------------------------------------------------
bool TClient::IsConnect(void)
{
	if(Context == NULL)
    	return false;

    bool Ret = false;

    __try
    {
    	Ret = Context->Connected();
    }
    catch(Exception &e)
    {

    }

    return Ret;
}

//---------------------------------------------------------------------------
// 접속
//---------------------------------------------------------------------------
void TClient::Connect(String pIP, int pPort)
{
	__try
	{
		Context->Connect(pIP, pPort);
	}
	catch(Exception &e)
	{
		printf("TClient::Connect() %s\n", e.Message.t_str());
	}
}

//---------------------------------------------------------------------------
// 접속 해제
//---------------------------------------------------------------------------
void TClient::Disconnect(void)
{
	__try
	{
		if(IsConnect())
        {
			Context->Disconnect();
            Context->IOHandler->InputBuffer->Clear();
        }

        printf("TClient::Disconnect()\n");
	}
	catch(Exception &e)
	{
	}
}

//---------------------------------------------------------------------------
// 패킷 보내기
//---------------------------------------------------------------------------
bool TClient::SendPacket(int pCmd, void *pBuffer, int pSize)
{
	int	Cmd		= pCmd;
    int	Size	= pSize;
    int Check	= Size - 1;

    TMemoryStream *SendStream	= new TMemoryStream;

	__try
    {
        __try
        {
            if(!IsConnect())
                return false;

            SendStream->Write(&Cmd, sizeof(int));
            SendStream->Write(&Size, sizeof(int));
            SendStream->Write(&Check, sizeof(int));

            if(pBuffer)
            	SendStream->Write(pBuffer, Size);

            SendStream->Position	= 0;
            Context->IOHandler->Write(SendStream, 0, true);
        }
        catch(Exception &e)
        {
            Disconnect();

            printf("TClient::SendPacket() %s, %I64d\n", e.Message.t_str(), SendStream->Size);

            return false;
        }
    }
    __finally
    {
    	delete SendStream;
    }

	return true;
}

//---------------------------------------------------------------------------
// 패킷 처리
//---------------------------------------------------------------------------
void __fastcall TClient::Execute(void)
{
    DWORD			Timer	= timeGetTime();
	int				Cmd, Size, Check;
    int				HEADER_SIZE	= 12;
    BYTE			Buffer[32767];

    TMemoryStream	*RecvStream	= new TMemoryStream;

	while(!Terminated)
	{
		Sleep(1);

        __try
        {
            if(!IsConnect())
                continue;

            RecvStream->Clear();
            Context->IOHandler->ReadStream(RecvStream);
            RecvStream->Position	= 0;

            while(RecvStream->Position < RecvStream->Size)
            {
                // 남아 있는 Stream 크기 측정
                if(RecvStream->Size - RecvStream->Position < HEADER_SIZE)
                {
                    printf("TClient::Execute() 남아있는 패킷량이 부족함 #1. %I64d, %I64d\n", RecvStream->Position, RecvStream->Size);

                    break;
                }

                // 패킷 헤더
                RecvStream->Read(&Cmd, sizeof(int));
                RecvStream->Read(&Size, sizeof(int));
                RecvStream->Read(&Check, sizeof(int));

                // 에러 검사
                if(Size != Check + 1)
                {
                    printf("TClient::Execute() 패킷 무결성 에러 - %x, %d - %I64d, %I64d, %d\n", Cmd, Check, Size, RecvStream->Position, RecvStream->Size);

                    break;
                }

                // 남아 있는 Stream 크기 측정
                if(RecvStream->Size - RecvStream->Position < Size)
                {
                    printf("TClient::Execute() 남아있는 패킷량이 부족함 #2. %I64d, %I64d\n", RecvStream->Position, RecvStream->Size);

                    break;
                }

                RecvStream->Read(Buffer, Size);

                // 패킷 처리
                switch(Cmd)
                {
                case 0xBFCF:

                    break;
                default:
                    printf("TClient::Execute() 알 수 없는 패킷 : 0x%02x, Size : %d", Cmd, Size);

                    Context->Disconnect();
                    Context->IOHandler->InputBuffer->Clear();

                    break;
                }
            }
        }
        // 정상 종료
        catch(EIdClosedSocket& e)
        {
            Context->Disconnect();
            Context->IOHandler->InputBuffer->Clear();

            continue;
        }
        catch(EIdException& e)
        {
            if(e.Message.Pos("racefully") <= 0)
                printf("접속 해제 #1 %s\n", e.Message.t_str());

            Context->Disconnect();
            Context->IOHandler->InputBuffer->Clear();

            continue;
        }
        catch(Exception& e)
        {
            printf("접속 해제 #2 %s\n", e.Message.t_str());

            Context->Disconnect();
            Context->IOHandler->InputBuffer->Clear();

            continue;
        }
        catch(...)
        {
            printf("접속 해제 #3\n");

            Context->Disconnect();
            Context->IOHandler->InputBuffer->Clear();

            continue;
        }
	}

    delete RecvStream;
}

