using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using SystemX.Net.BaseProtocol;

//프로토콜 직렬화/역직렬화 기능
//기본 프로토콜 정의 포함
namespace SystemX.Common.Serialization
{
    public static class SystemXNetSerialization
    {
        private const int MAX_STEP_PACKET_SIZE = 256000;

        public const int MAX_PACKET_SIZE = 512000; //1024000 <- 256000 <- 65536;
        //public const int MAX_PACKET_SIZE = 256000; //1024000 <- 256000 <- 65536;

        public const int PACKET_NUM = 251; // 250 <- 64;

        public static object SelectPacket(uint uiDataSize)
        {
            object objPacket = null;

            //uint uiLowBytes = 0;
            //uint uiHighBytes = 1024;
            //

            /*
            FieldInfo field = typeof(StructureToMarshalFrom).GetField("_value1");
            object[] attributes = field.GetCustomAttributes(typeof(MarshalAsAttribute), false);
            MarshalAsAttribute marshal = (MarshalAsAttribute) attributes[0];
            int sizeConst = marshal.SizeConst 
            */

            int iPacketPos = GetPacketPos(uiDataSize);
            objPacket = SetPacketObject(iPacketPos);

            /*
            for (int i = 0; i < PACKET_NUM; i++)
            {
                uiLowBytes = (uint)(1024 * i);
                uiHighBytes = (uint)(1024 * (i + 1));

                if (uiDataSize >= uiLowBytes && uiDataSize <= uiHighBytes)
                {
                    objPacket = SetPacketObject(i);

                    break;
                }
            }
            */

            return objPacket;
        }
        public static int SelectPacketSize(PACKET_SIZE SET_SIZE)
        {
            object objPacket = null;
            int iSetSize = 0;

            objPacket = SetPacketObject((int)SET_SIZE);

            HEADER_PACKET HeaderPacket = new HEADER_PACKET();
            int iHeadSize = Marshal.SizeOf(HeaderPacket);
            int iPacketSize = 0;

            if (objPacket != null)
                iPacketSize = Marshal.SizeOf(objPacket);

            iSetSize = iHeadSize + iPacketSize;

            return iSetSize;
        }
        //------------------------------------------------------------------------------------------
        private static int GetPacketPos(uint uiDataSize)
        {
            int uiGetSizeMajor = -1;

            /*uiGetSizeMajor = (int)(uiDataSize / 1024);
            int uiGetSizeMinor = (int)(uiDataSize % 1024);

            if (uiGetSizeMajor == 0)
                uiGetSizeMajor = 0;

            if (uiGetSizeMinor == 0)
                uiGetSizeMajor -= 1;*/

            if (uiDataSize > MAX_STEP_PACKET_SIZE)
            {
                if (uiDataSize <= 512000) uiGetSizeMajor = 250;

                /*
                else if (uiDataSize <= 1024000) uiGetSizeMajor = 251;
                else if (uiDataSize <= 2048000) uiGetSizeMajor = 252;
                else if (uiDataSize <= 3072000) uiGetSizeMajor = 253;
                else if (uiDataSize <= 4096000) uiGetSizeMajor = 254;
                else if (uiDataSize <= 5120000) uiGetSizeMajor = 255;
                else if (uiDataSize <= 6144000) uiGetSizeMajor = 256;
                else if (uiDataSize <= 7168000) uiGetSizeMajor = 257;
                else if (uiDataSize <= 8192000) uiGetSizeMajor = 258;
                else if (uiDataSize <= 9216000) uiGetSizeMajor = 259;
                else if (uiDataSize <= 10240000) uiGetSizeMajor = 260;
                */
            }
            else
            {
                uiGetSizeMajor = (int)(uiDataSize / 1024);
                int uiGetSizeMinor = (int)(uiDataSize % 1024);

                if (uiGetSizeMajor == 0)
                    uiGetSizeMajor = 0;

                if (uiGetSizeMinor == 0)
                    uiGetSizeMajor -= 1;
            }

            return uiGetSizeMajor;
        }
        //------------------------------------------------------------------------------------------
        private static object SetPacketObject(int iSelectPos)
        {
            object objPacket = null;

            switch (iSelectPos)
            {
                case 0: objPacket = new DATA_PACKET_1024(); break;
                case 1: objPacket = new DATA_PACKET_2048(); break;
                case 2: objPacket = new DATA_PACKET_3072(); break;
                case 3: objPacket = new DATA_PACKET_4096(); break;
                case 4: objPacket = new DATA_PACKET_5120(); break;
                case 5: objPacket = new DATA_PACKET_6144(); break;
                case 6: objPacket = new DATA_PACKET_7168(); break;
                case 7: objPacket = new DATA_PACKET_8192(); break;
                case 8: objPacket = new DATA_PACKET_9216(); break;
                case 9: objPacket = new DATA_PACKET_10240(); break;
                case 10: objPacket = new DATA_PACKET_11264(); break;
                case 11: objPacket = new DATA_PACKET_12288(); break;
                case 12: objPacket = new DATA_PACKET_13312(); break;
                case 13: objPacket = new DATA_PACKET_14336(); break;
                case 14: objPacket = new DATA_PACKET_15360(); break;
                case 15: objPacket = new DATA_PACKET_16384(); break;
                case 16: objPacket = new DATA_PACKET_17408(); break;
                case 17: objPacket = new DATA_PACKET_18432(); break;
                case 18: objPacket = new DATA_PACKET_19456(); break;
                case 19: objPacket = new DATA_PACKET_20480(); break;
                case 20: objPacket = new DATA_PACKET_21504(); break;
                case 21: objPacket = new DATA_PACKET_22528(); break;
                case 22: objPacket = new DATA_PACKET_23552(); break;
                case 23: objPacket = new DATA_PACKET_24576(); break;
                case 24: objPacket = new DATA_PACKET_25600(); break;
                case 25: objPacket = new DATA_PACKET_26624(); break;
                case 26: objPacket = new DATA_PACKET_27648(); break;
                case 27: objPacket = new DATA_PACKET_28672(); break;
                case 28: objPacket = new DATA_PACKET_29696(); break;
                case 29: objPacket = new DATA_PACKET_30720(); break;
                case 30: objPacket = new DATA_PACKET_31744(); break;
                case 31: objPacket = new DATA_PACKET_32768(); break;
                case 32: objPacket = new DATA_PACKET_33792(); break;
                case 33: objPacket = new DATA_PACKET_34816(); break;
                case 34: objPacket = new DATA_PACKET_35840(); break;
                case 35: objPacket = new DATA_PACKET_36864(); break;
                case 36: objPacket = new DATA_PACKET_37888(); break;
                case 37: objPacket = new DATA_PACKET_38912(); break;
                case 38: objPacket = new DATA_PACKET_39936(); break;
                case 39: objPacket = new DATA_PACKET_40960(); break;
                case 40: objPacket = new DATA_PACKET_41984(); break;
                case 41: objPacket = new DATA_PACKET_43008(); break;
                case 42: objPacket = new DATA_PACKET_44032(); break;
                case 43: objPacket = new DATA_PACKET_45056(); break;
                case 44: objPacket = new DATA_PACKET_46080(); break;
                case 45: objPacket = new DATA_PACKET_47104(); break;
                case 46: objPacket = new DATA_PACKET_48128(); break;
                case 47: objPacket = new DATA_PACKET_49152(); break;
                case 48: objPacket = new DATA_PACKET_50176(); break;
                case 49: objPacket = new DATA_PACKET_51200(); break;
                case 50: objPacket = new DATA_PACKET_52224(); break;
                case 51: objPacket = new DATA_PACKET_53248(); break;
                case 52: objPacket = new DATA_PACKET_54272(); break;
                case 53: objPacket = new DATA_PACKET_55296(); break;
                case 54: objPacket = new DATA_PACKET_56320(); break;
                case 55: objPacket = new DATA_PACKET_57344(); break;
                case 56: objPacket = new DATA_PACKET_58368(); break;
                case 57: objPacket = new DATA_PACKET_59392(); break;
                case 58: objPacket = new DATA_PACKET_60416(); break;
                case 59: objPacket = new DATA_PACKET_61440(); break;
                case 60: objPacket = new DATA_PACKET_62464(); break;
                case 61: objPacket = new DATA_PACKET_63488(); break;
                case 62: objPacket = new DATA_PACKET_64512(); break;
                case 63: objPacket = new DATA_PACKET_65536(); break;
                case 64: objPacket = new DATA_PACKET_66560(); break;
                case 65: objPacket = new DATA_PACKET_67584(); break;
                case 66: objPacket = new DATA_PACKET_68608(); break;
                case 67: objPacket = new DATA_PACKET_69632(); break;
                case 68: objPacket = new DATA_PACKET_70656(); break;
                case 69: objPacket = new DATA_PACKET_71680(); break;
                case 70: objPacket = new DATA_PACKET_72704(); break;
                case 71: objPacket = new DATA_PACKET_73728(); break;
                case 72: objPacket = new DATA_PACKET_74752(); break;
                case 73: objPacket = new DATA_PACKET_75776(); break;
                case 74: objPacket = new DATA_PACKET_76800(); break;
                case 75: objPacket = new DATA_PACKET_77824(); break;
                case 76: objPacket = new DATA_PACKET_78848(); break;
                case 77: objPacket = new DATA_PACKET_79872(); break;
                case 78: objPacket = new DATA_PACKET_80896(); break;
                case 79: objPacket = new DATA_PACKET_81920(); break;
                case 80: objPacket = new DATA_PACKET_82944(); break;
                case 81: objPacket = new DATA_PACKET_83968(); break;
                case 82: objPacket = new DATA_PACKET_84992(); break;
                case 83: objPacket = new DATA_PACKET_86016(); break;
                case 84: objPacket = new DATA_PACKET_87040(); break;
                case 85: objPacket = new DATA_PACKET_88064(); break;
                case 86: objPacket = new DATA_PACKET_89088(); break;
                case 87: objPacket = new DATA_PACKET_90112(); break;
                case 88: objPacket = new DATA_PACKET_91136(); break;
                case 89: objPacket = new DATA_PACKET_92160(); break;
                case 90: objPacket = new DATA_PACKET_93184(); break;
                case 91: objPacket = new DATA_PACKET_94208(); break;
                case 92: objPacket = new DATA_PACKET_95232(); break;
                case 93: objPacket = new DATA_PACKET_96256(); break;
                case 94: objPacket = new DATA_PACKET_97280(); break;
                case 95: objPacket = new DATA_PACKET_98304(); break;
                case 96: objPacket = new DATA_PACKET_99328(); break;
                case 97: objPacket = new DATA_PACKET_100352(); break;
                case 98: objPacket = new DATA_PACKET_101376(); break;
                case 99: objPacket = new DATA_PACKET_102400(); break;
                case 100: objPacket = new DATA_PACKET_103424(); break;
                case 101: objPacket = new DATA_PACKET_104448(); break;
                case 102: objPacket = new DATA_PACKET_105472(); break;
                case 103: objPacket = new DATA_PACKET_106496(); break;
                case 104: objPacket = new DATA_PACKET_107520(); break;
                case 105: objPacket = new DATA_PACKET_108544(); break;
                case 106: objPacket = new DATA_PACKET_109568(); break;
                case 107: objPacket = new DATA_PACKET_110592(); break;
                case 108: objPacket = new DATA_PACKET_111616(); break;
                case 109: objPacket = new DATA_PACKET_112640(); break;
                case 110: objPacket = new DATA_PACKET_113664(); break;
                case 111: objPacket = new DATA_PACKET_114688(); break;
                case 112: objPacket = new DATA_PACKET_115712(); break;
                case 113: objPacket = new DATA_PACKET_116736(); break;
                case 114: objPacket = new DATA_PACKET_117760(); break;
                case 115: objPacket = new DATA_PACKET_118784(); break;
                case 116: objPacket = new DATA_PACKET_119808(); break;
                case 117: objPacket = new DATA_PACKET_120832(); break;
                case 118: objPacket = new DATA_PACKET_121856(); break;
                case 119: objPacket = new DATA_PACKET_122880(); break;
                case 120: objPacket = new DATA_PACKET_123904(); break;
                case 121: objPacket = new DATA_PACKET_124928(); break;
                case 122: objPacket = new DATA_PACKET_125952(); break;
                case 123: objPacket = new DATA_PACKET_126976(); break;
                case 124: objPacket = new DATA_PACKET_128000(); break;
                case 125: objPacket = new DATA_PACKET_129024(); break;
                case 126: objPacket = new DATA_PACKET_130048(); break;
                case 127: objPacket = new DATA_PACKET_131072(); break;
                case 128: objPacket = new DATA_PACKET_132096(); break;
                case 129: objPacket = new DATA_PACKET_133120(); break;
                case 130: objPacket = new DATA_PACKET_134144(); break;
                case 131: objPacket = new DATA_PACKET_135168(); break;
                case 132: objPacket = new DATA_PACKET_136192(); break;
                case 133: objPacket = new DATA_PACKET_137216(); break;
                case 134: objPacket = new DATA_PACKET_138240(); break;
                case 135: objPacket = new DATA_PACKET_139264(); break;
                case 136: objPacket = new DATA_PACKET_140288(); break;
                case 137: objPacket = new DATA_PACKET_141312(); break;
                case 138: objPacket = new DATA_PACKET_142336(); break;
                case 139: objPacket = new DATA_PACKET_143360(); break;
                case 140: objPacket = new DATA_PACKET_144384(); break;
                case 141: objPacket = new DATA_PACKET_145408(); break;
                case 142: objPacket = new DATA_PACKET_146432(); break;
                case 143: objPacket = new DATA_PACKET_147456(); break;
                case 144: objPacket = new DATA_PACKET_148480(); break;
                case 145: objPacket = new DATA_PACKET_149504(); break;
                case 146: objPacket = new DATA_PACKET_150528(); break;
                case 147: objPacket = new DATA_PACKET_151552(); break;
                case 148: objPacket = new DATA_PACKET_152576(); break;
                case 149: objPacket = new DATA_PACKET_153600(); break;
                case 150: objPacket = new DATA_PACKET_154624(); break;
                case 151: objPacket = new DATA_PACKET_155648(); break;
                case 152: objPacket = new DATA_PACKET_156672(); break;
                case 153: objPacket = new DATA_PACKET_157696(); break;
                case 154: objPacket = new DATA_PACKET_158720(); break;
                case 155: objPacket = new DATA_PACKET_159744(); break;
                case 156: objPacket = new DATA_PACKET_160768(); break;
                case 157: objPacket = new DATA_PACKET_161792(); break;
                case 158: objPacket = new DATA_PACKET_162816(); break;
                case 159: objPacket = new DATA_PACKET_163840(); break;
                case 160: objPacket = new DATA_PACKET_164864(); break;
                case 161: objPacket = new DATA_PACKET_165888(); break;
                case 162: objPacket = new DATA_PACKET_166912(); break;
                case 163: objPacket = new DATA_PACKET_167936(); break;
                case 164: objPacket = new DATA_PACKET_168960(); break;
                case 165: objPacket = new DATA_PACKET_169984(); break;
                case 166: objPacket = new DATA_PACKET_171008(); break;
                case 167: objPacket = new DATA_PACKET_172032(); break;
                case 168: objPacket = new DATA_PACKET_173056(); break;
                case 169: objPacket = new DATA_PACKET_174080(); break;
                case 170: objPacket = new DATA_PACKET_175104(); break;
                case 171: objPacket = new DATA_PACKET_176128(); break;
                case 172: objPacket = new DATA_PACKET_177152(); break;
                case 173: objPacket = new DATA_PACKET_178176(); break;
                case 174: objPacket = new DATA_PACKET_179200(); break;
                case 175: objPacket = new DATA_PACKET_180224(); break;
                case 176: objPacket = new DATA_PACKET_181248(); break;
                case 177: objPacket = new DATA_PACKET_182272(); break;
                case 178: objPacket = new DATA_PACKET_183296(); break;
                case 179: objPacket = new DATA_PACKET_184320(); break;
                case 180: objPacket = new DATA_PACKET_185344(); break;
                case 181: objPacket = new DATA_PACKET_186368(); break;
                case 182: objPacket = new DATA_PACKET_187392(); break;
                case 183: objPacket = new DATA_PACKET_188416(); break;
                case 184: objPacket = new DATA_PACKET_189440(); break;
                case 185: objPacket = new DATA_PACKET_190464(); break;
                case 186: objPacket = new DATA_PACKET_191488(); break;
                case 187: objPacket = new DATA_PACKET_192512(); break;
                case 188: objPacket = new DATA_PACKET_193536(); break;
                case 189: objPacket = new DATA_PACKET_194560(); break;
                case 190: objPacket = new DATA_PACKET_195584(); break;
                case 191: objPacket = new DATA_PACKET_196608(); break;
                case 192: objPacket = new DATA_PACKET_197632(); break;
                case 193: objPacket = new DATA_PACKET_198656(); break;
                case 194: objPacket = new DATA_PACKET_199680(); break;
                case 195: objPacket = new DATA_PACKET_200704(); break;
                case 196: objPacket = new DATA_PACKET_201728(); break;
                case 197: objPacket = new DATA_PACKET_202752(); break;
                case 198: objPacket = new DATA_PACKET_203776(); break;
                case 199: objPacket = new DATA_PACKET_204800(); break;
                case 200: objPacket = new DATA_PACKET_205824(); break;
                case 201: objPacket = new DATA_PACKET_206848(); break;
                case 202: objPacket = new DATA_PACKET_207872(); break;
                case 203: objPacket = new DATA_PACKET_208896(); break;
                case 204: objPacket = new DATA_PACKET_209920(); break;
                case 205: objPacket = new DATA_PACKET_210944(); break;
                case 206: objPacket = new DATA_PACKET_211968(); break;
                case 207: objPacket = new DATA_PACKET_212992(); break;
                case 208: objPacket = new DATA_PACKET_214016(); break;
                case 209: objPacket = new DATA_PACKET_215040(); break;
                case 210: objPacket = new DATA_PACKET_216064(); break;
                case 211: objPacket = new DATA_PACKET_217088(); break;
                case 212: objPacket = new DATA_PACKET_218112(); break;
                case 213: objPacket = new DATA_PACKET_219136(); break;
                case 214: objPacket = new DATA_PACKET_220160(); break;
                case 215: objPacket = new DATA_PACKET_221184(); break;
                case 216: objPacket = new DATA_PACKET_222208(); break;
                case 217: objPacket = new DATA_PACKET_223232(); break;
                case 218: objPacket = new DATA_PACKET_224256(); break;
                case 219: objPacket = new DATA_PACKET_225280(); break;
                case 220: objPacket = new DATA_PACKET_226304(); break;
                case 221: objPacket = new DATA_PACKET_227328(); break;
                case 222: objPacket = new DATA_PACKET_228352(); break;
                case 223: objPacket = new DATA_PACKET_229376(); break;
                case 224: objPacket = new DATA_PACKET_230400(); break;
                case 225: objPacket = new DATA_PACKET_231424(); break;
                case 226: objPacket = new DATA_PACKET_232448(); break;
                case 227: objPacket = new DATA_PACKET_233472(); break;
                case 228: objPacket = new DATA_PACKET_234496(); break;
                case 229: objPacket = new DATA_PACKET_235520(); break;
                case 230: objPacket = new DATA_PACKET_236544(); break;
                case 231: objPacket = new DATA_PACKET_237568(); break;
                case 232: objPacket = new DATA_PACKET_238592(); break;
                case 233: objPacket = new DATA_PACKET_239616(); break;
                case 234: objPacket = new DATA_PACKET_240640(); break;
                case 235: objPacket = new DATA_PACKET_241664(); break;
                case 236: objPacket = new DATA_PACKET_242688(); break;
                case 237: objPacket = new DATA_PACKET_243712(); break;
                case 238: objPacket = new DATA_PACKET_244736(); break;
                case 239: objPacket = new DATA_PACKET_245760(); break;
                case 240: objPacket = new DATA_PACKET_246784(); break;
                case 241: objPacket = new DATA_PACKET_247808(); break;
                case 242: objPacket = new DATA_PACKET_248832(); break;
                case 243: objPacket = new DATA_PACKET_249856(); break;
                case 244: objPacket = new DATA_PACKET_250880(); break;
                case 245: objPacket = new DATA_PACKET_251904(); break;
                case 246: objPacket = new DATA_PACKET_252928(); break;
                case 247: objPacket = new DATA_PACKET_253952(); break;
                case 248: objPacket = new DATA_PACKET_254976(); break;
                case 249: objPacket = new DATA_PACKET_256000(); break;
                case 250: objPacket = new DATA_PACKET_512000(); break;

                /*
                case 251: objPacket = new DATA_PACKET_1024000(); break;
                case 252: objPacket = new DATA_PACKET_2048000(); break;
                case 253: objPacket = new DATA_PACKET_3072000(); break;
                case 254: objPacket = new DATA_PACKET_4096000(); break;
                case 255: objPacket = new DATA_PACKET_5120000(); break;
                case 256: objPacket = new DATA_PACKET_6144000(); break;
                case 257: objPacket = new DATA_PACKET_7168000(); break;
                case 258: objPacket = new DATA_PACKET_8192000(); break;
                case 259: objPacket = new DATA_PACKET_9216000(); break;
                case 260: objPacket = new DATA_PACKET_10240000(); break;
                */

                default: objPacket = null; break;
            }

            return objPacket;
        }
        //------------------------------------------------------------------------------------------
        public static byte[] RawSerialize(object ShmStruct, int irsStructSize)
        {
            IntPtr buffer = Marshal.AllocHGlobal(irsStructSize);
            Marshal.StructureToPtr(ShmStruct, buffer, false);
            byte[] RawData = new byte[irsStructSize];
            Marshal.Copy(buffer, RawData, 0, irsStructSize);
            Marshal.FreeHGlobal(buffer);
            return RawData;
        }
        //------------------------------------------------------------------------------------------
        public static object RawDeSerialize(byte[] RawData, Type typeData, int iOption = 0)
        {
            int RawSize = 0;

            if (iOption == 0)
                RawSize = Marshal.SizeOf(typeData);
            else
                RawSize = iOption;

            //Size Over
            if (RawSize > RawData.Length)
                return null;

            IntPtr buffer = Marshal.AllocHGlobal(RawSize);
            Marshal.Copy(RawData, 0, buffer, RawSize);
            object retobj = Marshal.PtrToStructure(buffer, typeData);
            Marshal.FreeHGlobal(buffer);
            return retobj;
        }
        //------------------------------------------------------------------------------------------
        public static byte[] ObjectToByteArray(object obj)
        {
            if (obj == null) return null;

            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            bf.Serialize(ms, obj);
            return ms.ToArray();
        }
        //------------------------------------------------------------------------------------------
        public static object ByteArrayToObject(byte[] byteArr)
        {
            if (byteArr == null) return null;

            MemoryStream ms = new MemoryStream();
            BinaryFormatter bf = new BinaryFormatter();
            ms.Write(byteArr, 0, byteArr.Length);
            ms.Seek(0, SeekOrigin.Begin);
            object obj = bf.Deserialize(ms);

            return obj;
        }
        public static T ByteArrayToObject<T>(byte[] byteArr)
        {
            if (byteArr == null) return default(T);

            MemoryStream ms = new MemoryStream();
            BinaryFormatter bf = new BinaryFormatter();
            ms.Write(byteArr, 0, byteArr.Length);
            ms.Seek(0, SeekOrigin.Begin);

            return (T)Convert.ChangeType(bf.Deserialize(ms), typeof(T)); 
        }
    }
}
