using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using SystemX.Common;
using SystemX.Common.Serialization;
using SystemX.Net.BaseProtocol;
using SystemX.Net.Schedule;
using SystemX.Net.XAdaptor;
using static SystemX.Net.Platform.Common.Util.LogMessage;

namespace SystemX.Net.XAdaptor.PC
{
    public partial class XAdaptorPC
    {
        public eResultCheck CheckIssuedID(string strProductID)
        {
            if(strProductID.Length <= 0)
                return eResultCheck.InvalidFormat;

            DataSet dsResult = WaitCallQuery("ID_IsIssued", strProductID);

            if (XCommons.isHasRow(dsResult))
                return eResultCheck.AlreadyIssued;
            else
                return eResultCheck.NotIssued;
        }

        //맥 어드레스 무결성 체크
        public eMacAddressType IsMacAddressForm(string strMacAddress)
        {
            // IP4 ADDRESS (25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}
            /* IP6 ADDRESS
            (([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:)
            {1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:)
            {1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4})
            {1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:)
            {1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})
            |:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]
            {1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}
            [0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]
            {1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]
            |(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))
            */
            // MAC ADDRESS
            // ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}
            //^([[:xdigit:]]{2}[:.-]?){5}[[:xdigit:]]{2}$
            //^([0-9a-fA-F]{2}[:.-]?){5}[0-9a-fA-F]{2}$/g
            Regex r1 = new Regex("^([0-9a-fA-F]{2}){5}[0-9a-fA-F]{2}$");
            Regex r2 = new Regex("^([0-9a-fA-F]{2}[:]+){5}[0-9a-fA-F]{2}$");
            Regex r3 = new Regex("^([0-9a-fA-F]{2}[-]+){5}[0-9a-fA-F]{2}$");
            Regex r4 = new Regex("^([0-9a-fA-F]{2}[.]+){5}[0-9a-fA-F]{2}$");
            Regex r5 = new Regex("^([0-9a-fA-F]{2}[:.-]?){5}[0-9a-fA-F]{2}$");

            bool b1 = r1.Match(strMacAddress).Success;
            bool b2 = r2.Match(strMacAddress).Success;
            bool b3 = r3.Match(strMacAddress).Success;
            bool b4 = r4.Match(strMacAddress).Success;
            bool b5 = r5.Match(strMacAddress).Success;

            eMacAddressType type = eMacAddressType.Normal;

            if (b5 == false)
                return eMacAddressType.InvalidMacAddressFormat;

            if (b2)
                type = eMacAddressType.Colon;
            else if (b3)
                type = eMacAddressType.Hyphen;
            else if (b4)
                type = eMacAddressType.Dot;

            return type;
        }

        private string MacAddressFormatRecalculation(string strMacAddress)
        {
            string strFindMacAddress = string.Empty;

            foreach (char c in strMacAddress)
            {
                if (char.IsLetterOrDigit(c))
                    strFindMacAddress += c;
            }

            return strFindMacAddress;
        }

        private string MacAddressFormatChange(string strText, eMacAddressType type)
        {
            string strChangeMacAddress = string.Empty;

            int nPos = 0;
            foreach (char c in strText)
            {
                if(nPos / 2 == 1)
                {
                    switch(type)
                    {
                        case eMacAddressType.Colon:
                            strChangeMacAddress += ":";
                            break;
                        case eMacAddressType.Hyphen:
                            strChangeMacAddress += "-";
                            break;
                        case eMacAddressType.Dot:
                            strChangeMacAddress += ".";
                            break;
                    }

                    nPos = 0;
                }

                if (char.IsLetterOrDigit(c))
                        strChangeMacAddress += c;

                nPos++;
            }

            return strChangeMacAddress;
        }


        //목록에 존재하는 맥어드레스 인지
        public bool CheckListMacAddress(string strMacAddress)
        {
            if (IsMacAddressForm(strMacAddress) == eMacAddressType.InvalidMacAddressFormat)
                return false;

            string strFindMacAddress = MacAddressFormatRecalculation(strMacAddress);

            DataSet dsResult = WaitCallQuery("MacAddress_Check", strFindMacAddress);

            if (XCommons.isHasRow(dsResult))
                return true;
            else
                return false;
        }

        public eResultCheck CheckIssuedMacAddress(string strMacAddress)
        {
            if (IsMacAddressForm(strMacAddress) == eMacAddressType.InvalidMacAddressFormat)
                return eResultCheck.InvalidMacAddressFormat;

            string strFindMacAddress = MacAddressFormatRecalculation(strMacAddress);

            DataSet dsResult = WaitCallQuery("MacAddress_IsIssued", strFindMacAddress);

            if (XCommons.isHasRow(dsResult))
                return eResultCheck.AlreadyIssued;
            else
                return eResultCheck.NotIssued;
        }
        private int GetCurrentQuantity()
        {
            int nCurCnt = int.MaxValue;

            DataSet dsResult = WaitCallQuery("Check_Mac_Quantity");

            try
            {
                if (XCommons.isHasRow(dsResult))
                {
                    if (int.TryParse(dsResult.Tables[0].Rows[0][0].ToString(), out nCurCnt) == false)
                        throw new Exception();
                }
                else
                    nCurCnt = int.MinValue;
            }
            catch
            {
                nCurCnt = int.MinValue;
            }

            return nCurCnt;
        }

        //현재 발행 예정 대상 주소
        public string GetToBeIssuedMacAddress(eMacAddressType type = eMacAddressType.Normal)
        {
            int nGetCurrent = GetCurrentQuantity();

            if (nGetCurrent == int.MaxValue || nGetCurrent == int.MinValue)
                return "";

            DataSet dsResult = WaitCallQuery("MacAddress_ToBeIssuedCheck", nGetCurrent.ToString());

            string strGetMacAddress = string.Empty;

            if (XCommons.isHasRow(dsResult))
            {
                strGetMacAddress = dsResult.Tables[0].Rows[0][1].ToString();

                strGetMacAddress = MacAddressFormatChange(strGetMacAddress, type);
            }

            return strGetMacAddress;
        }

        //총개수
        public int GetTotalAddressNumber()
        {
            DataSet dsResult = WaitCallQuery("Check_Mac_Quantity");

            int nValue = 0;

            if (XCommons.isHasRow(dsResult))
            {
                if (int.TryParse(dsResult.Tables[0].Rows[0][1].ToString(), out nValue) == false)
                    nValue = -1;
            }

            return nValue;
        }

        //발행 개수 확인
        public int GetCurrentIssuedAddressNumber()
        {
            DataSet dsResult = WaitCallQuery("Check_Mac_Quantity");

            int nValue = 0;

            if (XCommons.isHasRow(dsResult))
            {
                if (int.TryParse(dsResult.Tables[0].Rows[0][0].ToString(), out nValue) == false)
                    nValue = -1;
            }

            return nValue;
        }

        //남은 개수 확인
        public int GetRemainAddressNumber()
        {
            DataSet dsResult = WaitCallQuery("Check_Mac_Quantity");

            int nValue1 = 0;
            int nValue2 = 0;

            int nResult = 0;

            if (XCommons.isHasRow(dsResult))
            {
                if (int.TryParse(dsResult.Tables[0].Rows[0][0].ToString(), out nValue1) == false)
                    nValue1 = -1;
                if (int.TryParse(dsResult.Tables[0].Rows[0][1].ToString(), out nValue2) == false)
                    nValue2 = -1;

                if (nValue1 == -1 || nValue2 == -1)
                    nResult = -1;
                else
                    nResult = nValue2 - nValue1;
            }

            return nResult;
        }

        protected string GetTableValue(DataSet ds, string strParam1)
        {
            string strValue = string.Empty;

            if (strParam1.Length > 0)
            {
                int nIndex = int.MaxValue;

                if (int.TryParse(strParam1, out nIndex))
                    strValue = ds.Tables[0].Rows[0][nIndex].ToString();
                else
                    strValue = ds.Tables[0].Rows[0][strParam1].ToString();
            }
            else
                strValue = ds.Tables[0].Rows[0][0].ToString();

            return strValue;
        }

        public string LookUpIDbyMacAddress(string strMacAddress)
        {
            if (IsMacAddressForm(strMacAddress) == eMacAddressType.InvalidMacAddressFormat)
                return "InvalidMacAddressFormat";

            string strFindMacAddress = MacAddressFormatRecalculation(strMacAddress);

            DataSet dsResult = WaitCallQueryLookUp("LookUpID_ByMacAddress", strFindMacAddress);

            string strValue = string.Empty;

            if (XCommons.isHasRow(dsResult))
                strValue = GetTableValue(dsResult, QueryResult.strVarParam1);

            return strValue;
        }
        

        public string LookUpMacAddressbyID(ref string strProductID, eLookUpOption SetLookUpOption = eLookUpOption.CompareToSame, eMacAddressType type = eMacAddressType.Normal)
        {
            DataSet dsResult = null;
            
            if(SetLookUpOption == eLookUpOption.StartWith)
                dsResult = WaitCallQueryLookUp("LookUpMacAddress_ByLikeID", strProductID + "%");
            else if (SetLookUpOption == eLookUpOption.EndWith)
                dsResult = WaitCallQueryLookUp("LookUpMacAddress_ByLikeID", "%" + strProductID);
            else if(SetLookUpOption == eLookUpOption.ContainWith)
                dsResult = WaitCallQueryLookUp("LookUpMacAddress_ByLikeID", "%" + strProductID + "%");
            else
                dsResult = WaitCallQueryLookUp("LookUpMacAddress_ByID", strProductID);

            string strGetMacAddress = string.Empty;

            string strValue = string.Empty;

            if (XCommons.isHasRow(dsResult))
            {
                strValue = GetTableValue(dsResult, QueryResult.strVarParam1);

                strValue = MacAddressFormatChange(strValue, type);

                strProductID = dsResult.Tables[0].Rows[0][4].ToString();
            }

            return strValue;
        }

        private string RequestMacAddressIssuance(string strProductID, ref string strRetrunMessage, out int nErrCode, bool bReissuance = false)
        {
            nErrCode = int.MinValue;

            strRetrunMessage = string.Empty;

            string strGetUniqueInfo = string.Empty;

            if (thisConnInfo.ConnectCommandState == false)
                return "[Error] Need connect command socket.";
            if (thisConnInfo.InitialInfoState == false)
                return "[Error] Need InitialInfoState information.";
            if (LoadInfo.SIMPLE_LOOKUP_OPTION == true)
                return "[Error] Cannot do this in simple lookup mode.";

            try
            {
                thisConnInfo.OnCommandTime();

                try
                {
                    PROCESS_PACKET MakeProcessPacket = new PROCESS_PACKET();
                    int iSendSize = Marshal.SizeOf(MakeProcessPacket);
                    byte[] ucSendArray = new byte[iSendSize];
                    MakeProcessPacket = (PROCESS_PACKET)SystemXNetSerialization.RawDeSerialize(ucSendArray, MakeProcessPacket.GetType());

                    MakeProcessPacket.nStationID = 0;
                    MakeProcessPacket.objProdNo_C[0].Data = "";
                    MakeProcessPacket.objTestType[0].Data = "";
                    MakeProcessPacket.objTestCode[0].Data = ((bReissuance == false) ? "ISSUANCE" : "REISSUANCE");
                    MakeProcessPacket.objTestListFileVersion[0].Data = "";
                    MakeProcessPacket.objProductionCode[0].Data = "";
                    MakeProcessPacket.objProductID[0].Data = strProductID;

                    byte[] ucSendByteInfo = XCommons.SpecialObjectToByteStream(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.PROCESS_QUERY, BASE_PROTOCOL.OPTION_CODE.GET_ISSUANCE_MACADDRESS), MakeProcessPacket);

                    byte ucGetLabel = FlowCommandControl.InsertSendQueue(DateTime.Now, ucSendByteInfo, null, true);

                    WaitThreadJoin(waitCommandParam, FlowCommandControl, ucGetLabel);

                    if (XCommons.isHasRow(QueryResult.QueryDataSet))
                        strGetUniqueInfo = GetTableValue(QueryResult.QueryDataSet, QueryResult.strVarParam1);

                    int.TryParse(QueryResult.strVarParam3, out nErrCode);

                    strRetrunMessage = QueryResult.strVarParam2;
                }
                catch (Exception ex)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") +
                      @"MacAddress issuance request error. [SystemX.Net.XAdaptor.PC - IXPCAdaptor : RequestMacAddressIssuance]\r\n" +
                      ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
                }
                finally { }
            }
            finally
            {
                ;
            }

            return strGetUniqueInfo;
        }

        public ResultIssued IssuanceRequest(string strProductID, bool bReissuance = false, eMacAddressType type = eMacAddressType.Normal)
        {
            int nGetErrCode = 0;

            string strGetErrMsg = string.Empty;

            string strGetUniqueInfo = string.Empty;

            if (strProductID.Length <= 0)
                return new ResultIssued(eResultIssued.InvalidFormat);

            strGetUniqueInfo = RequestMacAddressIssuance(strProductID, ref strGetErrMsg, out nGetErrCode, bReissuance);     

            if(IsMacAddressForm(strGetUniqueInfo) != eMacAddressType.InvalidMacAddressFormat)
                strGetUniqueInfo = MacAddressFormatChange(strGetUniqueInfo, type);

            eResultIssued riReturn = eResultIssued.None;

            switch(nGetErrCode)
            {
                case 0:
                    riReturn = eResultIssued.Success;
                    break;
                case -2:
                    riReturn = eResultIssued.AlreadyIssued;
                    break;
                case -3:
                    riReturn = eResultIssued.InformationWithoutIssuanceHistory;
                    break;
                default:
                    riReturn = eResultIssued.Failed;
                    break;
            }

            return new ResultIssued(riReturn, strGetUniqueInfo, strGetErrMsg);
        }
    }
}
