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

#include <vcl.h>
#pragma hdrstop

#include "FrmCommLogF.h"
#include "VMSCommLibF.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFrmCommLog *FrmCommLog = NULL;
//---------------------------------------------------------------------------
__fastcall TFrmCommLog::TFrmCommLog(TComponent* Owner)
    : TForm(Owner)
{
    FObjCtlrIdx = -1;
    FObjCtlrId  = " ";
    FObjCtlr       = NULL;

    reMsg->Lines->Clear();
}
//---------------------------------------------------------------------------

void __fastcall TFrmCommLog::btnClearClick(TObject *Sender)
{
    try
    {
        reMsg->Lines->Clear();
        Application->ProcessMessages();
    }
    catch(Exception &e)
    {
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmCommLog::btnCopyClick(TObject *Sender)
{
    try
    {
        reMsg->SelectAll();
        reMsg->CopyToClipboard();
        Application->ProcessMessages();
    }
    catch(Exception &e)
    {
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmCommLog::OnWMLogDisplayMessage(TMessage &Msg)
{
    if (!Showing) return;
    if (chkLogPause->Checked) return;

    IPC_LOG_MESSAGE *pLog = (IPC_LOG_MESSAGE *)Msg.WParam;
    if (pLog)
    {
#if 0
        IPC_LOG_MESSAGE Log;
        Log.Kind = pLog->Kind;
        Log.Flag = pLog->Flag;
        Log.Len  = pLog->Len;
        Log.Tm   = pLog->Tm;
        Log.Type = pLog->Type;
        memcpy(Log.Msg, pLog->Msg, sizeof(Log.Msg));
        //ReplyMessage(0);
        LogWrite(&Log);
#else
        LogWrite(pLog);
#endif
    }
}
//---------------------------------------------------------------------------

void TFrmCommLog::LogWrite(IPC_LOG_MESSAGE *ALog)
{
    if (chkLogPause->Checked) return;

    if (!ALog) return;

    if (ALog->Type == 'S')
    {
        if (!chkServer->Checked) return;
    }
    else
    {
        if (!chkClient->Checked) return;
    }

    if (ALog->Kind == eLOG_DATA)
    {
        LogData(ALog);
        return;
    }

    try
    {
        //reMsg->Lines->BeginUpdate();

        AnsiString  sLogKind = " [XXX] ";
        switch(ALog->Kind)
        {
        case eLOG_INFO   : sLogKind = " [INF] "; break;
        case eLOG_DATA   : sLogKind = " [DAT] "; break;
        case eLOG_ERROR  : sLogKind = " [ERR] "; break;
        case eLOG_WARNING: sLogKind = " [WAN] "; break;
        case eLOG_DEBUG  : sLogKind = " [DBG] "; break;
        case eLOG_DETAIL : sLogKind = " [DET] "; break;
        }
        try
        {
#if 0
            while (reMsg->Lines->Count >= g_AppCfg.nMaxLogLines)
                reMsg->Lines->Delete(0);
#else
            if (reMsg->Lines->Count >= g_AppCfg.nMaxLogLines)
                reMsg->Lines->Clear();
#endif

            reMsg->Lines->Add(ALog->Tm.FormatString("hh:nn:ss") + "." + Now().FormatString("ss") + sLogKind + String(ALog->Msg));
            //reMsg->Lines->Add(ALog->Tm.FormatString("hh:nn:ss") + "." + Now().FormatString("ss") + String(ALog->Msg));
            //reMsg->Lines->Add(ALog->Tm.FormatString("hh:nn:ss") + String(ALog->Msg));
        }
        catch(Exception &e)
        {
        }
    }
    __finally
    {
        //reMsg->Lines->EndUpdate();
        //SendMessage(reMsg->Handle, EM_SCROLLCARET, 0, 0);
        //reMsg->Perform(EM_SCROLLCARET, 0, 0);
        //Application->ProcessMessages();
    }
}
//---------------------------------------------------------------------------

void TFrmCommLog::LogData(IPC_LOG_MESSAGE *ALog)
{
    AnsiString     sTemp;
    AnsiString     sTime;
    int            ii, jj, pos;
    bool           bFileClose = false;
    unsigned char *AData= ALog->Msg;

    if (!AData) return;

    AnsiString sLogData = "";
    AnsiString sDispLog = "";
    if (chkLogPause->Checked) return;

    try
    {
        //reMsg->Lines->BeginUpdate();

        try
        {
            AnsiString sSndRcv = ALog->Flag == 1 ? "SEND" : "RECV";
            sTime = AnsiString(ALog->Tm.FormatString("hh:nn:ss") + "." + Now().FormatString("ss"));
            if (ALog->Type == 'C')
                sTemp.printf("%s [DATA] %s, [%s] %d Bytes ", sTime.c_str(), FObjCtlrId.c_str(), sSndRcv.c_str(), ALog->Len);
            else
                sTemp.printf("%s [DATA] %s, [%s] %d Bytes ", sTime.c_str(), FObjCtlrId.c_str(), sSndRcv.c_str(), ALog->Len);

            reMsg->Lines->Add("");
            reMsg->Lines->Add(sTemp);

            AnsiString sLog;
            AnsiString sChar;
            AnsiString sMsg;

            for (ii = 0; ii < ALog->Len; ii += 16)
            {
                sLogData = "";
                sLog = "";
                sMsg.printf("%08Xh ", ii);
                sLog += sMsg;
                for (jj = 0; jj < 16; jj++)
                {
                    pos = ii + jj;
                    if (pos < ALog->Len)
                        sMsg.printf(" %02X", AData[pos]);
                    else
                        sMsg.printf("   ");

                    sLog += sMsg;

                    if (jj == 7)
                    {
                        //sMsg.printf("  "); sLog += sMsg;
                    }
                }

                sMsg.printf("  ;"); sLog += sMsg;

                for (jj = 0; jj < 16; jj++)
                {
                    pos = ii + jj;
                    if (pos >= ALog->Len)
                        break;

                    uint8_t v = AData[pos];
                    sMsg.printf("%c", isprint(v) ? v : '.');
                    sLog += sMsg;
                    if (jj == 7)
                    {
                        //sMsg.printf(" "); sLog += sMsg;
                    }
                }
                sLogData += sLog;
                sDispLog += sLogData;
                sDispLog += "\r\n";
                ////sLogData = sLogData.SubString(0, sLogData.Length()-2);
                //reMsg->Lines->Add(sLogData);
            }
            reMsg->Lines->Add(sDispLog);
            //reMsg->Lines->Add("");
        }
        catch(Exception &e)
        {
        }
    }
    __finally
    {
        //reMsg->Lines->EndUpdate();
        //SendMessage(reMsg->Handle, EM_SCROLLCARET, 0, 0);
        //reMsg->Perform(EM_SCROLLCARET, 0, 0);
        //Application->ProcessMessages();
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmCommLog::FormClose(TObject *Sender, TCloseAction &Action)
{
    ResetDisplayLog();
    Hide();
}
//---------------------------------------------------------------------------

void __fastcall TFrmCommLog::ResetDisplayLog(int AControllerIdx/*=-1*/)
{
    if (FObjCtlr)
    {
        FObjCtlr->FDispLog = false;
        FObjCtlr->FCLog->FLogCfg = g_LogCfg;
        FObjCtlr->FSLog->FLogCfg = g_LogCfg;
    }
    if (AControllerIdx < 0)
    {
        FObjCtlr = NULL;
        return;
    }

    TCDSCtlr *pOldCtlr = FObjCtlr;

    FObjCtlr = (TCDSCtlr*)AControllerIdx;
    FObjCtlr->FCLog->FLogCfg = g_LogCfg;
    FObjCtlr->FSLog->FLogCfg = g_LogCfg;

    FLogCfg = FObjCtlr->FSLog->FLogCfg;

    chkInfo->Checked    = FLogCfg.Info;
    chkData->Checked    = FLogCfg.Data;
    chkError->Checked   = FLogCfg.Error;
    chkWarning->Checked = FLogCfg.Warning;
    chkDebug->Checked   = FLogCfg.Debug;
    chkDetail->Checked  = FLogCfg.Detail;

    FObjCtlr->FDispLog = true;
    FObjCtlrId = FObjCtlr->CTLR_ID;

    Caption = FObjCtlr->CTLR_ID + ", " + FObjCtlr->NM;

    if (pOldCtlr != FObjCtlr)
    {
        btnClearClick(NULL);
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmCommLog::btnSetLogClick(TObject *Sender)
{
    FLogCfg.Info    = chkInfo->Checked;
    FLogCfg.Data    = chkData->Checked;
    FLogCfg.Error   = chkError->Checked;
    FLogCfg.Warning = chkWarning->Checked;
    FLogCfg.Debug   = chkDebug->Checked;
    FLogCfg.Detail  = chkDetail->Checked;

    if (FObjCtlr)
    {
        FObjCtlr->FCLog->FLogCfg = FLogCfg;
        FObjCtlr->FSLog->FLogCfg = FLogCfg;
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmCommLog::FormShow(TObject *Sender)
{
    Application->ProcessMessages();
}
//---------------------------------------------------------------------------

void TFrmCommLog::DisplayMsg(String& AMsg)
{
    if (chkLogPause->Checked) return;
    if (!Showing) return;

    if (reMsg->Lines->Count >= g_AppCfg.nMaxLogLines)
        reMsg->Lines->Clear();

	if (AMsg != "")
	{
		AMsg[AMsg.Length()-1] = 0;	// 마지막줄의 CRLF 삭제. 그래야 메모장에서는 줄간 간격이 떨어지지 않게 찍힌다.
		reMsg->Lines->Add(AMsg);
	}
}
//---------------------------------------------------------------------------


