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

#include <vcl.h>
#pragma hdrstop

#include "FrmVmsInfoF.h"
#include "FrmVmsLogF.h"
#include "FrmMainF.h"
#include "AppGlobalF.h"
#include "VMSCThread.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "cxCalc"
#pragma link "cxClasses"
#pragma link "cxControls"
#pragma link "cxCustomData"
#pragma link "cxData"
#pragma link "cxDataStorage"
#pragma link "cxEdit"
#pragma link "cxFilter"
#pragma link "cxGraphics"
#pragma link "cxGrid"
#pragma link "cxGridCustomTableView"
#pragma link "cxGridCustomView"
#pragma link "cxGridLevel"
#pragma link "cxGridTableView"
#pragma link "cxLabel"
#pragma link "cxLookAndFeelPainters"
#pragma link "cxLookAndFeels"
#pragma link "cxStyles"
#pragma resource "*.dfm"
TFrmVmsInfo *FrmVmsInfo = NULL;

String VmsModuleType(TVmsCtlr *AObj)
{
#ifdef LANG_ENG
    if (AObj->VmsType == "VUTN") return "Text";
    return "Figure";
#else
    if (AObj->VmsType == "VUTN") return "문자식";
    return "도형식";
#endif
}
//---------------------------------------------------------------------------

String VmsOperMode(TVmsCtlr *AObj)
{
#ifdef LANG_ENG
    if (AObj->OPER_MODE == "A") return "Auto";
    return "Fixed";
#else
    if (AObj->OPER_MODE == "A") return "자동";
    return "고정";
#endif
}
//---------------------------------------------------------------------------

String VmsComm(TVmsCtlr *AObj)
{
#ifdef LANG_ENG
    if (AObj->Client.Comm == state_open) return "Normal";
    return "Error";
#else
    if (AObj->Client.Comm == state_open) return "정상";
    return "장애";
#endif
}
//---------------------------------------------------------------------------

String VmsModuleState(TVmsCtlr *AObj)
{
#ifdef LANG_ENG
    if (AObj->Client.Comm != state_open) return "-";
    if (AObj->RSTATE.ModuleState == vms_normal) return "Normal";
    return "Error";
#else
    if (AObj->Client.Comm != state_open) return "-";
    if (AObj->RSTATE.ModuleState == vms_normal) return "정상";
    return "장애";
#endif
}
//---------------------------------------------------------------------------

String VmsModulePower(TVmsCtlr *AObj)
{
#ifdef LANG_ENG
    if (AObj->Client.Comm != state_open) return "-";
    if (AObj->RSTATE.ModulePowerStatus == vms_on) return "On";
    return "Off";
#else
    if (AObj->Client.Comm != state_open) return "-";
    if (AObj->RSTATE.ModulePowerStatus == vms_on) return "켜짐";
    return "꺼짐";
#endif
}
//---------------------------------------------------------------------------

String VmsModuleLuminance(TVmsCtlr *AObj)
{
    if (AObj->Client.Comm != state_open) return "-";
    int nLuminance = AObj->RSTATE.LuminanceStatus;
    return String(nLuminance);
}
//---------------------------------------------------------------------------

String VmsModuleDoor(TVmsCtlr *AObj)
{
#ifdef LANG_ENG
    if (AObj->Client.Comm != state_open) return "-";
    if (AObj->RSTATE.DoorStatus == vms_open) return "Open";
    return "Close";
#else
    if (AObj->Client.Comm != state_open) return "-";
    if (AObj->RSTATE.DoorStatus == vms_open) return "열림";
    return "닫힘";
#endif
}
//---------------------------------------------------------------------------


String VmsModuleFan(TVmsCtlr *AObj)
{
#ifdef LANG_ENG
    if (AObj->Client.Comm != state_open) return "-";
    if (AObj->RSTATE.FanStatus == vms_on) return "On";
    return "Off";
#else
    if (AObj->Client.Comm != state_open) return "-";
    if (AObj->RSTATE.FanStatus == vms_on) return "동작";
    return "정지";
#endif
}
//---------------------------------------------------------------------------


String VmsModuleHeater(TVmsCtlr *AObj)
{
#ifdef LANG_ENG
    if (AObj->Client.Comm != state_open) return "-";
    if (AObj->RSTATE.HeaterStatus == vms_on) return "On";
    return "Off";
#else
    if (AObj->Client.Comm != state_open) return "-";
    if (AObj->RSTATE.HeaterStatus == vms_on) return "가동";
    return "중지";
#endif
}
//---------------------------------------------------------------------------


String VmsModuleTemp(TVmsCtlr *AObj)
{
    if (AObj->Client.Comm != state_open) return "-";
    int nTemp = AObj->RSTATE.BodyTemp;
    return String(nTemp);//+"℃";
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
__fastcall TFrmVmsInfo::TFrmVmsInfo(TComponent* Owner)
    : TForm(Owner)
{
    FViewMode = 0;
    FVmsCnt = 0;
}
//---------------------------------------------------------------------------

void __fastcall TFrmVmsInfo::InitVmsList()
{
    int nRow;
    TcxDataController *pGDC = TvList->DataController;

    try
    {
        TvList->BeginUpdate();
        pGDC->BeginUpdate();
        pGDC->RecordCount = 0;

        VmsIterator it;
        for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
        {
            TVmsCtlr *pObj = (TVmsCtlr*)it->second;
            nRow = pGDC->AppendRecord();

            pGDC->Values[nRow][Col00->Index] = process_stop;
            pGDC->Values[nRow][Col01->Index] = "";
            pGDC->Values[nRow][Col02->Index] = pObj->VmsNo;
            pGDC->Values[nRow][Col03->Index] = pObj->VmsId;
            pGDC->Values[nRow][Col04->Index] = pObj->Name;
            pGDC->Values[nRow][Col05->Index] = pObj->IpAddress + "." + String(pObj->LocalNo);
            pGDC->Values[nRow][Col06->Index] = "-";
            pGDC->Values[nRow][Col07->Index] = "-";
            pGDC->Values[nRow][Col08->Index] = "-";
            pGDC->Values[nRow][Col09->Index] = "-";
            pGDC->Values[nRow][Col10->Index] = "-";
            pGDC->Values[nRow][Col11->Index] = "-";
            pGDC->Values[nRow][Col12->Index] = "-";
            pGDC->Values[nRow][Col13->Index] = "-";
            pGDC->Values[nRow][Col14->Index] = "-";
            pGDC->Values[nRow][Col15->Index] = "-";

            pGDC->Values[nRow][Col99->Index] = (int)pObj;

            pObj->RowNo = nRow;
        }
    }
    __finally
    {
        pGDC->EndUpdate();
        TvList->EndUpdate();
        FVmsCnt = pGDC->RecordCount;
    }

    VmsManager->Total  = VmsManager->Count;
    VmsManager->Error  = VmsManager->Count;
    VmsManager->Normal = 0;
    VmsManager->Module = 0;

    plTot->Caption = String(VmsManager->Count);
    plErr->Caption = String(VmsManager->Count);
    plNor->Caption = "0";
}
//---------------------------------------------------------------------------

void __fastcall TFrmVmsInfo::UpdateServerState(int AObj)
{
    TcxDataController *pGDC = TvList->DataController;
    try
    {
        int       nErrCnt = 0;
        int       nMemPtr;
        TVmsCtlr *pObj;
        for (int nRow = 0; nRow < FVmsCnt; nRow++)
        {
            nMemPtr = pGDC->Values[nRow][Col99->Index];
            pObj = (TVmsCtlr*)nMemPtr;
            if (!pObj) continue;

            //TODO
            pGDC->Values[nRow][Col00->Index] = pObj->Client.Comm;
            pObj->Server.Status = pObj->Client.Comm == state_open ? process_run : process_fail;
            if (pObj->Server.Status != process_run)
            {
                pGDC->Values[nRow][Col00->Index] = process_stop;
                nErrCnt++;
            }
            pGDC->Values[nRow][Col14->Index] = pObj->ConnectTm;       //Connect
            pGDC->Values[nRow][Col15->Index] = pObj->DisconnectTm;    //Disconnect
        }

        VmsManager->Error  = nErrCnt;
        VmsManager->Normal = FVmsCnt-nErrCnt;
        plTot->Caption = String(FVmsCnt);
        plErr->Caption = String(nErrCnt);
        plNor->Caption = String(FVmsCnt-nErrCnt);
    }
    catch(Exception &e)
    {
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmVmsInfo::UpdateClientState(int AObj)
{
#ifdef LANG_ENG
    String sNormal = "Normal";
    String sError  = "Error";
#else
    String sNormal = "정상";
    String sError  = "오류";
#endif

    TcxDataController *pGDC = TvList->DataController;
    try
    {
        int       nMemPtr;
        TVmsCtlr *pObj;
        for(int nRow = 0; nRow < FVmsCnt; nRow++)
        {
            nMemPtr = pGDC->Values[nRow][Col99->Index];
            pObj = (TVmsCtlr*)nMemPtr;
            if (!pObj) continue;

            if (pObj->Client.Status == process_run)
            {
                if (pObj->Client.Comm == state_open)
                    pGDC->Values[nRow][Col06->Index] = sNormal;
                else
                    pGDC->Values[nRow][Col06->Index] = "-";
            }
            else
            {
                pGDC->Values[nRow][Col06->Index] = sError;
            }

            pGDC->Values[nRow][Col07->Index] = VmsModuleState(pObj);      //모듈
            pGDC->Values[nRow][Col08->Index] = VmsModuleLuminance(pObj);  //휘도
            pGDC->Values[nRow][Col09->Index] = VmsModulePower(pObj);      //전원
            pGDC->Values[nRow][Col10->Index] = VmsModuleDoor(pObj);       //도어
            pGDC->Values[nRow][Col11->Index] = VmsModuleFan(pObj);        //팬
            pGDC->Values[nRow][Col12->Index] = VmsModuleHeater(pObj);     //히터
            pGDC->Values[nRow][Col13->Index] = VmsModuleTemp(pObj);       //온도
        }
    }
    catch(Exception &e)
    {
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmVmsInfo::Col01CustomDrawCell(TcxCustomGridTableView *Sender, TcxCanvas *ACanvas,
          TcxGridTableDataCellViewInfo *AViewInfo, bool &ADone)
{
    if (AViewInfo->GridRecord->RecordIndex < 0) return;

    Graphics::TBitmap *pBmp = NULL;
    pBmp = ImgState1->Picture->Bitmap;
	if (!VarIsNull(AViewInfo->GridRecord->DisplayTexts[Col00->Index]))
    {
        String sCode = AViewInfo->GridRecord->DisplayTexts[Col00->Index];
        int    nCode = sCode.ToIntDef(2);

        if      (nCode == process_run ) pBmp = ImgState0->Picture->Bitmap;
        else if (nCode == process_stop) pBmp = ImgState1->Picture->Bitmap;
        else                            pBmp = ImgState3->Picture->Bitmap;
    }

    if (!pBmp) return;
    pBmp->Transparent = true;

    int nW, nH;
    nW = nH = 21;
    try
    {
        TColor bBrush = ACanvas->Brush->Color;
        if (AViewInfo->GridRecord->Selected)
        {
            if (AViewInfo->GridRecord->Index % 2 == 0)
            {
                bBrush = Sender->LookAndFeelPainter->DefaultContentEvenColor();
            }
            else
            {
                bBrush = Sender->LookAndFeelPainter->DefaultContentOddColor();
            }
        }
        ACanvas->Brush->Color = bBrush;

        TRect rc;
        TRect rcOrg = AViewInfo->Bounds;
        ACanvas->FillRect(rcOrg);

        nW = rcOrg.Bottom - rcOrg.Top - 4;
        rc.Top    = rcOrg.Top+2;
        rc.Bottom = rcOrg.Bottom - 2;
        rc.Left   = rcOrg.Left + (rcOrg.Width() - nW) / 2;
        rc.Right  = rc.Left + nW;

        ACanvas->Canvas->StretchDraw(rc, pBmp);
        //ACanvas->Draw(AViewInfo->ContentBounds.Left, AViewInfo->ContentBounds.Top, pBmp);
        ADone = true;
    }
    catch(...) {}
}
//---------------------------------------------------------------------------

void __fastcall TFrmVmsInfo::TvListCellDblClick(TcxCustomGridTableView *Sender, TcxGridTableDataCellViewInfo *ACellViewInfo,
          TMouseButton AButton, TShiftState AShift,
          bool &AHandled)
{
    if (!ACellViewInfo) return;
    try {
        TcxDataController *pGDC = TvList->DataController;
        int nRow = pGDC->FocusedRecordIndex;
        if (nRow < 0) return;

        int nMemPtr = pGDC->Values[nRow][Col99->Index];
        if (!nMemPtr) return;

        if (!FrmVmsLog->Showing)
        {
            FrmVmsLog->Top = FrmMain->Top;
            //FrmVmsLog->Left= FrmMain->Left+FrmMain->Width;
            FrmVmsLog->Show();
        }
        FrmVmsLog->DisplayVmsLog(nMemPtr);
    } catch(...) {}
}
//---------------------------------------------------------------------------

void __fastcall TFrmVmsInfo::TvListCellClick(TcxCustomGridTableView *Sender, TcxGridTableDataCellViewInfo *ACellViewInfo,
          TMouseButton AButton, TShiftState AShift,
          bool &AHandled)
{
	if (AButton != mbRight) return;
    if (!ACellViewInfo) return;

    try {
        TcxDataController *pGDC = TvList->DataController;
        int nRow = pGDC->FocusedRecordIndex;
        if (nRow < 0) return;

        FSelVmsNo = VarToStr(pGDC->Values[nRow][Col02->Index]);
        FSelVmsNm = VarToStr(pGDC->Values[nRow][Col04->Index]);

        POINT p;
        GetCursorPos(&p);

        pmuVms->Popup(p.x, p.y);
    } catch(...) {}
}
//---------------------------------------------------------------------------

void __fastcall TFrmVmsInfo::pmuVmsPopup(TObject *Sender)
{
    MnuVmsId->Caption = FSelVmsNm;
}
//---------------------------------------------------------------------------

void __fastcall TFrmVmsInfo::mnuVmsPowerOnClick(TObject *Sender)
{
    TMenuItem *pMnu = (TMenuItem*)Sender;

    TVmsCtlr *pObj = VmsManager->FLists.Find(FSelVmsNo);
    if (!pObj) return;

    if (pObj->Server.Status != process_run) return;

    if (!pObj->pPackQueue) return;

    String sVmsNmbr = FSelVmsNo;

    int nCmdIdx;
    if (pMnu->Tag == 0)
        nCmdIdx = vms_board_power_on;
    else
    if (pMnu->Tag == 1)
        nCmdIdx = vms_board_power_off;
    else
    if (pMnu->Tag == 2)
    {
        nCmdIdx = 2;
    }
    else
        return;

    String sCmdUser = "server";
    String sCmdTime = Now().FormatString("yyyymmddhhnnss");
    BYTE   OpCode;

    if (nCmdIdx == vms_board_power_on || nCmdIdx == vms_board_power_off)
    {
        OpCode = INT_OP_VMS_POWER_CTL;

        // 전광판 On(=0)/Off(=1)
        INT_VMS_POWER_CTL_REQ VmsPowerCtl;
        BYTE                  MsgSeq;

        memset(&VmsPowerCtl, 0x00, sizeof(VmsPowerCtl));

        MsgSeq = (BYTE)0x10;                                                            // 제어명령 일련번호-결과값을 받아서 처리할때 필요함

        memcpy(VmsPowerCtl.CmdTime, AnsiString(sCmdTime).c_str(), INT_VMS_MAX_DATETIME); /* 명령수행시각 */
        memcpy(VmsPowerCtl.VmsId,   AnsiString(sVmsNmbr).c_str(), INT_VMS_MAX_ID);       /* VMS 제어기 번호 */
        memcpy(VmsPowerCtl.OperId,  AnsiString(sCmdUser).c_str(), INT_VMS_MAX_OPER_ID);  /* 운영자 ID */
        VmsPowerCtl.Command = (BYTE)nCmdIdx;                                            /* 제어 구분, 0:켜짐 1:꺼짐 */

        IPCUDPPACKET *pPI = new IPCUDPPACKET;
        if (pPI == NULL) return;

        pPI->Sender.IP   = 0;
        pPI->Sender.Port = 0;
        pPI->RecvId      = 0;
        pPI->OPCode      = OpCode;
        pPI->Size        = (int)sizeof(VmsPowerCtl);
        if (pPI->Size > 0)
        {
            pPI->Data = new char[pPI->Size];
            if (!pPI->Data)
            {
                delete pPI;
                return ;
            }
            CopyMemory(pPI->Data, (char*)&VmsPowerCtl, pPI->Size);
        }
        pObj->pPackQueue->Add((void*)pPI);
    }
    else
    if (nCmdIdx == 2)
    {
        OpCode = INT_OP_VMS_RESET;

        // 제어기 리셋
        INT_VMS_RESET_REQ VmsReset;
        BYTE              MsgSeq;

        memset(&VmsReset, 0x00, sizeof(VmsReset));

        MsgSeq = (BYTE)0x20;
        memcpy(VmsReset.CmdTime, AnsiString(sCmdTime).c_str(), INT_VMS_MAX_DATETIME); /* 명령수행시각 */
        memcpy(VmsReset.VmsId,   AnsiString(sVmsNmbr).c_str(), INT_VMS_MAX_ID);       /* VMS 제어기 번호 */
        memcpy(VmsReset.OperId,  AnsiString(sCmdUser).c_str(), INT_VMS_MAX_OPER_ID);  /* 운영자 ID */

        IPCUDPPACKET *pPI = new IPCUDPPACKET;
        if (pPI == NULL) return;

        pPI->Sender.IP   = 0;
        pPI->Sender.Port = 0;
        pPI->RecvId      = 0;
        pPI->OPCode      = OpCode;
        pPI->Size        = (int)sizeof(VmsReset);
        if (pPI->Size > 0)
        {
            pPI->Data = new char[pPI->Size];
            if (!pPI->Data)
            {
                delete pPI;
                return ;
            }
            CopyMemory(pPI->Data, (char*)&VmsReset, pPI->Size);
        }
        pObj->pPackQueue->Add((void*)pPI);
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmVmsInfo::mnuVmsStatusReqClick(TObject *Sender)
{
    TVmsCtlr *pObj = VmsManager->FLists.Find(FSelVmsNo);
    if (!pObj) return;

    if ((pObj->Client.pThread         != NULL) &&
        (pObj->Client.ActiveIndicator == true))
    {
        try
        {
            TVMSCThread *pVMSCThread = (TVMSCThread *)pObj->Client.pThread;
            pVMSCThread->ReqStatus();
        }
        catch(Exception &e)
        {
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmVmsInfo::mnuVmsFormDnClick(TObject *Sender)
{
    TVmsCtlr *pObj = VmsManager->FLists.Find(FSelVmsNo);
    if (!pObj) return;

    if ((pObj->Client.pThread         != NULL) &&
        (pObj->Client.ActiveIndicator == true))
    {
        TVmsFormManager *m_pVmsFormList = pObj->pForms;

		m_pVmsFormList->Lock();
		try
		{
            int nFormCnt = m_pVmsFormList->Count();
            for (int ii = 0; ii < nFormCnt; ii++)
            {
                TVmsForm *pVmsForm = m_pVmsFormList->GetItem(ii);
                if (pVmsForm)
                {
                    pVmsForm->SvcRes = false;
                }
            }
		}
		__finally
		{
            pObj->CTLMODE->Enable = object_enable;
			m_pVmsFormList->UnLock();
		}
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmVmsInfo::Disconnect1Click(TObject *Sender)
{
    TVmsCtlr *pObj = VmsManager->FLists.Find(FSelVmsNo);
    if (!pObj) return;

    if ((pObj->Client.pThread         != NULL) &&
        (pObj->Client.ActiveIndicator == true))
    {
        try
        {
            TVMSCThread *pVMSCThread = (TVMSCThread *)pObj->Client.pThread;
            pVMSCThread->FUserTerm = true;
        }
        catch(Exception &e)
        {
        }
    }
}
//---------------------------------------------------------------------------

