using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace SystemX.Net.BaseProtocol
{
    [Serializable]
    public enum PROCESS_TYPE
    {
        NONE = -1,
        SYSTEM = 0,
        PLC = 1,
        PC = 2,
        DEVICE = 3,
        UIM = 4,
        UIM_SERVER = 5,
        PC_PORT_SERVER = 6
    }

    /*
     *  Adaptor
     */
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct STRING_4
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct STRING_8
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct STRING_16
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct STRING_32
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct STRING_64
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct STRING_128
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct STRING_256
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct STRING_512
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct STRING_1024
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct STRING_2048
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2048)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct STRING_4096
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4096)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    /*
     * System Query
     */
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
    public struct QUERY_STRING
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2048)]
        public string Data;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct SYSTEMTIME
    {
        public short wYear;
        public short wMonth;
        public short wDayOfWeek;
        public short wDay;
        public short wHour;
        public short wMinute;
        public short wSecond;
        public short wMilliseconds;
    }
    //------------------------------------------------------------------------------------------
    /*
     *  Initialize Comm Body
     */
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct COMM_INFO_PACKET
    {
        //Use Port Distribution
        [MarshalAs(UnmanagedType.Bool)]
        public bool bPortDistribution;

        //COMMAND 포트 번호
        [MarshalAs(UnmanagedType.U2)]
        public ushort usPortCommandNumber;

        //STREAM 포트 번호
        [MarshalAs(UnmanagedType.U2)]
        public ushort usPortStreamNumber;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_32[] objConnLocalAddress;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_32[] objConnLocalPort;
    }
    //------------------------------------------------------------------------------------------
    /*
     *  Initialize Comm Body
     */
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct PING_PACKET
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_8[] objCheckMsg;
    }
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct TIME_PACKET
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_32[] objMsg;
        
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public SYSTEMTIME[] objTime;
    }
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct MESSAGE_PACKET
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_512[] objMessage;
    }
    //------------------------------------------------------------------------------------------
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct TRANSFER_PACKET
    {
        //수신 결과
        [MarshalAs(UnmanagedType.Bool)]
        public bool bRecvResult;

        //처리 결과
        [MarshalAs(UnmanagedType.Bool)]
        public bool bProcessResult;
    }
    //------------------------------------------------------------------------------------------

    //------------------------------------------------------------------------------------------
    /*
     *  Packet Header
     */
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct HEADER_PACKET
    {
        [MarshalAs(UnmanagedType.U2)]
        public ushort usHeader;

        //응답 결과
        [MarshalAs(UnmanagedType.Bool)]
        public bool bResponsState;

        //네트워크 번호
        [MarshalAs(UnmanagedType.U1)]
        public byte ucNetworkNo;

        //데이터베이스 ID
        [MarshalAs(UnmanagedType.U1)]
        public byte ucDatabaseID;

        //테이블 ID
        [MarshalAs(UnmanagedType.U2)]
        public ushort usTableID;
        
        //Pallet Number
        [MarshalAs(UnmanagedType.U1)]
        public byte ucPalletNumber;

        //Pallet Index
        [MarshalAs(UnmanagedType.U2)]
        public ushort usPalletIndex;

        //해당 헤더 크기
        [MarshalAs(UnmanagedType.U4)]
        public uint uiHeaderLength;

        //선택된 바디 패킷 길이
        [MarshalAs(UnmanagedType.U4)]
        public uint uiBodyLength;

        //전체 패킷 크기
        [MarshalAs(UnmanagedType.U4)]
        public uint uiPacketLength;

        //실제 데이터 크기
        [MarshalAs(UnmanagedType.U4)]
        public uint uiDataLength;

        //로그 파일 전송시 이름
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_128[] objOptionName;

        //최종 변환 확장자 명
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_8[] objOptionExtension;

        //연속 패킷(대용량) 현재 번호 Default 0 Else 1 ~
        [MarshalAs(UnmanagedType.U4)]
        public uint uiSourDataNum;

        //연속 패킷(대용량) 최종 번호 Default 0 Else 1 ~
        [MarshalAs(UnmanagedType.U4)]
        public uint uiDestDataNum;

        //주 명령
        [MarshalAs(UnmanagedType.U2)]
        public ushort usCommand;

        //서브 명령
        [MarshalAs(UnmanagedType.U2)]
        public ushort usSubCommand;

        //옵션 명령
        [MarshalAs(UnmanagedType.U4)]
        public uint uiOptionCommand;

        //다목적 사용 파라미터1
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_64[] objVarParam1;

        //다목적 사용 파라미터2
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_128[] objVarParam2;

        //다목적 사용 파라미터3
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_256[] objVarParam3;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public CP_PACKET[] objCP_Packet;
    }
    //------------------------------------------------------------------------------------------

    /*
     *  CP Info Header
     */
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct CP_PACKET
    {
        //CP ALIS StationName
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_64[] objStationName;

        //CP ALIS ProdP
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_16[] objProdNo_P;

        //CP ALIS ProdC
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_16[] objProdNo_C;

        //CP ALIS TestType
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_8[] objTestType;

        //CP ALIS TestCode
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_16[] objTestCode;

        //CP ALIS Version
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_4[] objVersion;

        //CP ALIS ProdCode
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_4[] objProdCode;

        //CP ALIS TestListNo
        [MarshalAs(UnmanagedType.U4)]
        public uint uiTestListNo;
    }
    //------------------------------------------------------------------------------------------

    /*
     *  PLC Adaptor 지원
     */
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct USER_PACKET
    {
        //파레트 정보 및 제품 아이디 및 품번
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public PROCESS_PACKET[] objProcessInfo;

        //명령 INSERT, UPDATE, DELETE SELECT 등 현재는 INSERT 만.
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_16[] objTableCommand;

        //테이블 명칭
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_64[] objTableName;

        //컬럼 길이
        [MarshalAs(UnmanagedType.U4)]
        public uint uiSubLength;

        //0 부터 해당 컬럼 명
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_512[] objNames;

        //0 부터 해당 컬럼 데이터
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_512[] objDatas;

        //처리 결과
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_16[] objCommandResult;
    }
    //------------------------------------------------------------------------------------------
    /*
     *  SYSTEM 지원
     */
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct QUERY_PACKET
    {
        //QUERY 문
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public QUERY_STRING[] objQueryText;
        //다목적 파라미터1
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_64[] objVarParam1;
        //다목적 파라미터2
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_128[] objVarParam2;
        //다목적 파라미터3
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_256[] objVarParam3;
    }
    //------------------------------------------------------------------------------------------
    /*
     *  HOST LOGIN
     */
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct SYSTEM_HOST_PACKET
    {
        //UIM Use
        [MarshalAs(UnmanagedType.Bool)]
        public bool bUseUIM;
        //UIM Use
        [MarshalAs(UnmanagedType.Bool)]
        public bool bUseSimpleLookupOption;
        //HOST ID
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_64[] objHostID;
        //SECTION
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_64[] objSection;
        //TEST CODE
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_64[] objTestCode;
        //MESSAGE
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_512[] objMessage;
    }
    //------------------------------------------------------------------------------------------
    /*
     *  PROCESS QUERY(PC, PLC Adaptor) 지원
     */
    [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
    public struct PROCESS_PACKET
    {
        //Station ID
        [MarshalAs(UnmanagedType.U4)]
        public uint nStationID;

        //ProdC
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_16[] objProdNo_C;

        //TestType
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_8[] objTestType;

        //TestCode
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_16[] objTestCode;

        //FileVersion
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_4[] objTestListFileVersion;

        //ProductionCode
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_4[] objProductionCode;

        //Product ID
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public STRING_64[] objProductID;
    }
    //------------------------------------------------------------------------------------------
    public class BASE_PROTOCOL
    {
        //BASE PROTOCOL Main Command 0 - Private
        public enum PROTOCOL_CODE
        {
            NONE = -1,
            //PC Adaptor File Save
            FILE_TRANSFER = 0,
            DATASET_TRANSEFER = 1,
            //Just reply
            SIMPLE_RESPONSE = 2,
            //PLC Adaptor
            ETC = 3,
            RAW_SIZE = 4,
            RAW_END = 5,
            //System Program
            SYSTEM_QUERY = 6,
            INITILALIZE_INFO = 7,     
            PROCESS_QUERY = 8,
            USER_QUERY = 9,
            TRANSFER_RESULT = 10,

            //Time Server Sync Request
            SYNC_TIME_SERVER = 128,
            //Host Info Check
            HOST_INFO_CHECK = 256,
            //Middleware send message
            MIDDLEWARE_MESSAGE = 512,
            //Ping
            CONNECT_STATE = 1024
        }
        [Flags]
        public enum OPTION_CODE
        {
            NONE = 0x00000000,
            QUERY_TESTLIST = 0x00000001,
            GET_ISSUANCE_MACADDRESS = 0x00000002,
            CHECK_VAILD_TESTLIST = 0x00000004,
        }
        public OPTION_CODE GetOptionCode()
        {
            return (OPTION_CODE)uiOptionCommand;
        }
        public void SetOptionCode(OPTION_CODE SET_OPTION)
        {
            uiOptionCommand = (uint)SET_OPTION;
        }
        //
        private ushort usCommand;
        private ushort usSubCommand;
        private uint uiOptionCommand;

        public PROTOCOL_CODE GET_CURRENT_PROTOCOL
        {
            get { return ProtocolDecoder(); }
        }
        public ushort COMMAND
        {
            get { return usCommand; }
        }
        public ushort SUB_COMMAND
        {
            get { return usSubCommand; }
        }
        public uint OPTION_COMMAND
        {
            get { return uiOptionCommand; }
        }

        public PROTOCOL_CODE ProtocolDecoder()
        {
            PROTOCOL_CODE SET_CODE = new PROTOCOL_CODE();
            SET_CODE = PROTOCOL_CODE.NONE;

            string TextCode = usCommand.ToString("D3") + "_" + usSubCommand.ToString("D3");

            if (TextCode.CompareTo("000_001") == 0)
                SET_CODE = PROTOCOL_CODE.FILE_TRANSFER;
            else if (TextCode.CompareTo("000_002") == 0)
                SET_CODE = PROTOCOL_CODE.DATASET_TRANSEFER;
            else if (TextCode.CompareTo("000_003") == 0)
                SET_CODE = PROTOCOL_CODE.SIMPLE_RESPONSE;
            else if (TextCode.CompareTo("000_004") == 0)
                SET_CODE = PROTOCOL_CODE.RAW_SIZE;
            else if (TextCode.CompareTo("000_005") == 0)
                SET_CODE = PROTOCOL_CODE.RAW_END;
            else if (TextCode.CompareTo("000_006") == 0)
                SET_CODE = PROTOCOL_CODE.SYSTEM_QUERY;
            else if (TextCode.CompareTo("000_007") == 0)
                SET_CODE = PROTOCOL_CODE.INITILALIZE_INFO;
            else if (TextCode.CompareTo("000_009") == 0)
                SET_CODE = PROTOCOL_CODE.USER_QUERY;
            else if (TextCode.CompareTo("000_010") == 0)
                SET_CODE = PROTOCOL_CODE.TRANSFER_RESULT;

            else if (TextCode.CompareTo("001_000") == 0)
                SET_CODE = PROTOCOL_CODE.ETC;

            else if (TextCode.CompareTo("002_001") == 0)
                SET_CODE = PROTOCOL_CODE.PROCESS_QUERY;

            else if (TextCode.CompareTo("999_004") == 0)
                SET_CODE = PROTOCOL_CODE.SYNC_TIME_SERVER;

            else if (TextCode.CompareTo("999_003") == 0)
                SET_CODE = PROTOCOL_CODE.HOST_INFO_CHECK;

            else if (TextCode.CompareTo("999_002") == 0)
                SET_CODE = PROTOCOL_CODE.MIDDLEWARE_MESSAGE;

            else if (TextCode.CompareTo("999_001") == 0)
                SET_CODE = PROTOCOL_CODE.CONNECT_STATE;

            else
                SET_CODE = PROTOCOL_CODE.NONE;

            return SET_CODE;
        }
        public BASE_PROTOCOL()
        {
        }
        public BASE_PROTOCOL(ushort usGetCommnad, ushort usGetSubCommand, uint uiGetOptionCommand = 0)
        {
            usCommand = usGetCommnad;
            usSubCommand = usGetSubCommand;
            //
            uiOptionCommand = uiGetOptionCommand;
        }
        /*
        public void PROTOCOL_CHANGE(PROTOCOL_CODE SET_CODE, OPTION_CODE SET_OPTION = OPTION_CODE.NONE)
        {
            new BASE_PROTOCOL(SET_CODE, SET_OPTION);
        }
        */
        public BASE_PROTOCOL(PROTOCOL_CODE SET_CODE, OPTION_CODE SET_OPTION = OPTION_CODE.NONE)
        {
            uiOptionCommand = (uint)SET_OPTION;

            if (SET_CODE == PROTOCOL_CODE.NONE)
            {
                usCommand = 0;
                usSubCommand = 0;
            }
            else if (SET_CODE == PROTOCOL_CODE.FILE_TRANSFER)
            {
                usCommand = 0;
                usSubCommand = 1;
            }
            else if (SET_CODE == PROTOCOL_CODE.DATASET_TRANSEFER)
            {
                usCommand = 0;
                usSubCommand = 2;
            }
            else if (SET_CODE == PROTOCOL_CODE.SIMPLE_RESPONSE)
            {
                usCommand = 0;
                usSubCommand = 3;
            }
            else if (SET_CODE == PROTOCOL_CODE.RAW_SIZE)
            {
                usCommand = 0;
                usSubCommand = 4;
            }
            else if (SET_CODE == PROTOCOL_CODE.RAW_END)
            {
                usCommand = 0;
                usSubCommand = 5;
            }
            else if (SET_CODE == PROTOCOL_CODE.SYSTEM_QUERY)
            {
                usCommand = 0;
                usSubCommand = 6;
            }
            else if (SET_CODE == PROTOCOL_CODE.INITILALIZE_INFO)
            {
                usCommand = 0;
                usSubCommand = 7;
            }
            else if (SET_CODE == PROTOCOL_CODE.USER_QUERY)
            {
                usCommand = 0;
                usSubCommand = 9;
            }
            else if (SET_CODE == PROTOCOL_CODE.TRANSFER_RESULT)
            {
                usCommand = 0;
                usSubCommand = 10;
            }
            //
            else if (SET_CODE == PROTOCOL_CODE.ETC)
            {
                usCommand = 1;
                usSubCommand = 0;
            }

            else if (SET_CODE == PROTOCOL_CODE.PROCESS_QUERY)
            {
                usCommand = 2;
                usSubCommand = 1;
            }

            else if (SET_CODE == PROTOCOL_CODE.SYNC_TIME_SERVER)
            {
                usCommand = 999;
                usSubCommand = 4;
            }

            else if (SET_CODE == PROTOCOL_CODE.HOST_INFO_CHECK)
            {
                usCommand = 999;
                usSubCommand = 3;
            }

            else if (SET_CODE == PROTOCOL_CODE.MIDDLEWARE_MESSAGE)
            {
                usCommand = 999;
                usSubCommand = 2;
            }

            else if (SET_CODE == PROTOCOL_CODE.CONNECT_STATE)
            {
                usCommand = 999;
                usSubCommand = 1;
            }

            else
            {
                usCommand = 0;
                usSubCommand = 0;
            }
        }
    }
}
