using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using SystemX.Common;
using SystemX.Common.Serialization;
using SystemX.Net.BaseProtocol;
using SystemX.Net.Schedule;
using static SystemX.Net.DB.XDBConnManager;
using static SystemX.Net.MiddlewareUI.MainForm;

namespace SystemX.Net.MiddlewareUI.UIM.Protocol_Method
{
    public class HOST_INFO_CHECK : ProtocolShell, IProtocol
    {
        public HOST_INFO_CHECK(MainForm parent, int iPos, byte nLabel)
        : base(parent, iPos, nLabel)
        {
        }

        public override void ExecuteProtocol(BASE_PROTOCOL GET_PROTOCOL,
            BASE_PROTOCOL.PROTOCOL_CODE CODE,
            HEADER_PACKET getHeader,
            object objData)
        {
            SYSTEM_HOST_PACKET usPacket = (SYSTEM_HOST_PACKET)objData;

            bool bGetUseUIM = usPacket.bUseUIM;
            bool bGetUseSimpleLookupOption = usPacket.bUseSimpleLookupOption;

            string strGetHostID = usPacket.objHostID[0].Data;

            if (bGetUseUIM && bGetUseSimpleLookupOption)
                strGetHostID = "SIMPLE-LOOKUP";
                    
            string strGetSection = usPacket.objSection[0].Data;
            string strGetTestCode = usPacket.objTestCode[0].Data;
            string strGetMessage = usPacket.objMessage[0].Data;

            SYSTEM_HOST_PACKET MakeLoginPacket = new SYSTEM_HOST_PACKET();
            int iSendSize = Marshal.SizeOf(MakeLoginPacket);
            byte[] ucSendArray = new byte[iSendSize];
            MakeLoginPacket = (SYSTEM_HOST_PACKET)SystemXNetSerialization.RawDeSerialize(ucSendArray, MakeLoginPacket.GetType());

            MakeLoginPacket.objHostID[0].Data = strGetHostID;
            MakeLoginPacket.objSection[0].Data = strGetSection;
            MakeLoginPacket.objTestCode[0].Data = strGetTestCode;

            try
            {
                ConnectInfoStore thisConnInfo = Parent_.GetConnectInfo(nPos) as ConnectInfoStore;

                bool bForcePass = false;

                DataTable dtHostTable = null;
                DataTable dtUserTable = null;

                DataRow[] drFindInfo = null;

                thisConnInfo.bHostLoginState = false;

                bool bUseExist = true;

                if (bGetUseUIM && bGetUseSimpleLookupOption)
                    bForcePass = true;

                if (bForcePass == false)
                {
                    dtHostTable = Parent_.GetDBConn().CurrentConnection(eConnCategory.Main).GetHostList(true);
                    dtUserTable = Parent_.GetDBConn().CurrentConnection(eConnCategory.Main).GetUserList(true);

                    if (bGetUseUIM)
                        drFindInfo = dtUserTable.Select($"UserID='{strGetHostID}' AND Password='{strGetSection}'");
                    else
                        drFindInfo = dtHostTable.Select($"HostID='{strGetHostID}' AND Section='{strGetSection}'");

                    bUseExist = Parent_.GetConnectInfoFindHost(strGetHostID, strGetSection, bGetUseUIM);
                }

                if (((drFindInfo != null ? drFindInfo.Count() > 0 : false) && 
                    bUseExist == false) ||
                    bForcePass)
                {
                    string strRegIP = string.Empty;
                    string strConnectIP = string.Empty;
                    string strRegTestCode = string.Empty;

                    if (drFindInfo[0].Table.Columns.Contains("TestCode"))
                        strRegTestCode = drFindInfo[0]["TestCode"].ToString();

                    if (bGetUseUIM == false)
                        strRegIP = drFindInfo[0]["IP"].ToString();

                    strConnectIP = thisConnInfo.strCommandEndPointInfo;

                    //TODO : For Test Server Code
                    if (true || strConnectIP.IndexOf(strRegIP) >= 0 || bGetUseUIM)
                    {
                        ;//IP Address Compare Result PASS
                        //
                        //
                    }
                    else
                    {
                        MakeLoginPacket.objMessage[0].Data = $"HostID={strGetHostID} Section={strGetSection} [FAIL] It is not the IP address specified in the host information.";

                        throw new Exception("[IP Address Check Error]");
                    }

                    bool bTestCodeCompareResult = true;

                    if (strRegTestCode.Length > 0)
                    {
                        if (strRegTestCode.CompareTo(strGetTestCode) != 0)
                        {
                            bTestCodeCompareResult = false;

                            MakeLoginPacket.objMessage[0].Data = $"HostID={strGetHostID} Section={strGetSection} ServerCode={strRegTestCode} ClientCode={strGetTestCode} [FAIL] The host's registered test code and the test code sent by the client do not match.";
                        }
                    }

                    if (bTestCodeCompareResult == false)
                    {
                        throw new Exception("[TestCode Check Error]");
                    }

                    MakeLoginPacket.objMessage[0].Data = $"HostID={strGetHostID} Section={strGetSection} [SUCCESS] Welcome.";

                    thisConnInfo.strConnectHostID = strGetHostID;

                    if (bGetUseUIM == false)
                        thisConnInfo.strConnectSection = strGetSection;
                    else
                    {
                        thisConnInfo.strConnectSection = strConnectIP;

                        MakeLoginPacket.objMessage[0].Data = $"HostID={strGetHostID} Section={thisConnInfo.strConnectSection} [SUCCESS] Welcome.";
                    }

                    string strHostSectionInfo =
                    thisConnInfo.strConnectHostID + ";" +
                    thisConnInfo.strConnectSection;

                    if (Parent_.TestListCntID.ContainsKey(strHostSectionInfo))
                        Parent_.TestListCntID[strHostSectionInfo].Clear();

                    thisConnInfo.strResultTestListCntID = string.Empty;

                    Parent_.SetLoginState(strGetHostID, thisConnInfo.strConnectSection, true);

                    thisConnInfo.bHostLoginState = true;
                }
                else
                {
                    if(bUseExist)
                        MakeLoginPacket.objMessage[0].Data = $"HostID={strGetHostID} Section={strGetSection} [FAIL] HOST ID already in use.";
                    else
                        MakeLoginPacket.objMessage[0].Data = $"HostID={strGetHostID} Section={strGetSection} [FAIL] That information does not exist.";
                }
            }
            catch(Exception ex)
            {
                MakeLoginPacket.objMessage[0].Data = $"HostID={strGetHostID} Section={strGetSection} [FAIL] Middleware login process error. " + ex.Message;
            }

            ucSendByteInfo = XCommons.SpecialObjectToByteStream(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.HOST_INFO_CHECK), MakeLoginPacket);
        }
    }
}
