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

namespace TestLib
{
    public class CTConvert
    {

        public static float limit = 1000000000000000;
        /// <summary>
        /// 将指定类型的littleEndian数据转换为BigEndian的字节序列
        /// </summary>
        /// <typeparam name="T">需要转换的类型</typeparam>
        /// <param name="buffer">接收转换后的字节序列的目标数组</param>
        /// <param name="offset">目标数组开始复制字节序列的起始索引</param>
        /// <param name="pars">需要转换的数据，数量可变</param>
        public static void ToBytesBigEndian<T>(byte[] buffer, int offset, params T[] pars) where T : struct
        {
            int nOffset = offset;
            foreach (T t in pars)
            {
                byte[] bt = StructToBytes(t);

                for (int i = bt.Length - 1; i >= 0; i--)
                {
                    buffer[nOffset++] = bt[i];
                }
            }
        }


        /// <summary>
        /// 将指定类型的littleEndian数据转换为BigEndian的字节序列
        /// </summary>
        /// <typeparam name="T">需要转换的类型</typeparam>
        /// <param name="buffer">接收转换后的字节序列的目标数组</param>
        /// <param name="offset">目标数组开始复制字节序列的起始索引</param>
        /// <param name="pars">需要转换的数据，数量可变</param>
        public static void ToBytesBigEndian2<T>(byte[] buffer, int offset, params T[] pars) where T : struct
        {
            int nOffset = offset;
            foreach (T t in pars)
            {
                byte[] bt = StructToBytes(t);

                for (int i = 0; i < bt.Length; i++)
                {
                    buffer[nOffset++] = bt[i];
                }
            }
        }

        /// <summary>
        /// 将BigEndian的字节序列转换为指定类型的littleEndian数据
        /// </summary>
        /// <typeparam name="T">需要转换的类型</typeparam>
        /// <param name="buffer">存储需要转换的字节序列的数组</param>
        /// <param name="offset">数组开始转换字节序列的起始索引</param>
        /// <returns>经过转换的值</returns>
        public static T FromBytesBigEndian<T>(byte[] buffer, int offset) where T : struct
        {
            int nOffset = offset;
            T val = new T();
            byte[] bt = StructToBytes(val);
            for (int i = bt.Length - 1; i >= 0; i--)
            {
                bt[i] = buffer[nOffset++];
            }
            val = (T)BytesToStruct(bt, bt.Length, typeof(T));
            return val;
        }

        public static T FromBytesBigEndian2<T>(byte[] buffer, int offset) where T : struct
        {
            int nOffset = offset;
            T val = new T();
            byte[] bt = StructToBytes(val);
            for (int i = 0; i < bt.Length; i++)
            {
                bt[i] = buffer[nOffset++];
            }
            val = (T)BytesToStruct(bt, bt.Length, typeof(T));
            return val;
        }


        /// <summary>
        /// 将字节序列转换为DateTime，字节序列依次为，年月星期日时分秒，每个一字节，一共七字节
        /// 其中，年为2000开始，即转换范围为2000-2255年
        /// </summary>
        /// <param name="buffer">存储需要转换的字节序列的数组</param>
        /// <param name="offset">数组开始转换字节序列的起始索引</param>
        /// <returns>经过转换后的值</returns>
        public static DateTime Bytes2DateTime(byte[] buffer, int offset)
        {
            DateTime dt = DateTime.MinValue;
            if (buffer == null) return dt;
            if (offset < 0 || offset > buffer.Length - 1) return dt;
            if (buffer.Length - offset < 6) return dt;
            try
            {
                dt = new DateTime(buffer[offset] + 2000,
                    buffer[offset + 1],
                    buffer[offset + 3],
                    buffer[offset + 4],
                    buffer[offset + 5],
                    buffer[offset + 6]
                    );
            }
            catch
            {
            }
            return dt;
        }
        private static DateTime dtLast = DateTime.Now.AddDays(-1);
        /// <summary>
        /// 将字节序列转换为DateTime，字节序列依次为，年月日时分秒，每个一字节，一共6字节
        /// 其中，年为2000开始，即转换范围为2000-2255年
        /// </summary>
        public static DateTime Bytes2DateTime2(byte[] buffer, int offset)
        {
            DateTime dt = DateTime.MinValue;
            if (buffer == null) return dt;
            if (offset < 0 || offset > buffer.Length - 1) return dt;
            if (buffer.Length - offset < 6) return dt;
            try
            {
                dt = new DateTime
                    (buffer[offset] + 2000,
                    buffer[offset + 1],
                    buffer[offset + 2],
                    buffer[offset + 3],
                    buffer[offset + 4],
                    buffer[offset + 5]
                    );
                dtLast = dt;
            }
            catch(Exception ex)
            {
                //dt = dtLast.AddHours(1);
                //dtLast = dt;
            }
            return dt;
        }

        public static DateTime Bytes2DateTime3(byte[] buffer, int offset)
        {
            DateTime dt = DateTime.MinValue;
            if (buffer == null) return dt;
            if (offset < 0 || offset > buffer.Length - 1) return dt;
            if (buffer.Length - offset < 7) return dt;
            try
            {
                dt = new DateTime(FromBytesBigEndian2<short>(buffer, offset),
                    buffer[offset + 2],
                    buffer[offset + 3],
                    buffer[offset + 4],
                    buffer[offset + 5],
                    buffer[offset + 6]
                    );
            }
            catch
            { }
            return dt;
        }

        /// <summary>
        /// 将DateTime转换为字节序列，字节序列依次为，年月星期日时分秒，每个一字节，一共七字节
        /// 其中，年为2000开始，即转换范围为2000-2255年
        /// </summary>
        /// <param name="buffer">存储转换后的字节序列的数组</param>
        /// <param name="offset">数组开始复制转换后的字节序列的起始索引</param>
        /// <param name="dt">需要转换的时间</param>
        public static void DateTime2Bytes(byte[] buffer, int offset, DateTime dt)
        {
            if (buffer == null) return;
            if (offset < 0 || offset > buffer.Length - 1) return;
            if (buffer.Length - offset < 6) return;
            buffer[offset] = (Byte)(dt.Year - 2000);
            buffer[offset + 1] = (Byte)dt.Month;
            buffer[offset + 2] = (Byte)dt.DayOfWeek;
            buffer[offset + 3] = (Byte)dt.Day;
            buffer[offset + 4] = (Byte)dt.Hour;
            buffer[offset + 5] = (Byte)dt.Minute;
            buffer[offset + 6] = (Byte)dt.Second;
        }

        public static void DateTime2Bytes3(byte[] buffer, int offset, DateTime dt)
        {
            if (buffer == null) return;
            if (offset < 0 || offset > buffer.Length - 1) return;
            if (buffer.Length - offset < 6) return;
            buffer[offset] = (Byte)(dt.Year - 2000);
            buffer[offset + 1] = (Byte)dt.Month;
            buffer[offset + 2] = (Byte)dt.Day;
            buffer[offset + 3] = (Byte)dt.DayOfWeek;           
            buffer[offset + 4] = (Byte)dt.Hour;
            buffer[offset + 5] = (Byte)dt.Minute;
            buffer[offset + 6] = (Byte)dt.Second;
        }

        /// <summary>
        /// 将DateTime转换为字节序列，字节序列依次为，年月日时分秒，每个一字节，一共6字节
        /// 其中，年为2000开始，即转换范围为2000-2255年
        /// </summary>
        /// <param name="buffer">存储转换后的字节序列的数组</param>
        /// <param name="offset">数组开始复制转换后的字节序列的起始索引</param>
        /// <param name="dt">需要转换的时间</param>
        public static void DateTime2Bytes2(byte[] buffer, int offset, DateTime dt)
        {
            if (buffer == null) return;
            if (offset < 0 || offset > buffer.Length - 1) return;
            if (buffer.Length - offset < 6) return;
            if (dt == DateTime.MinValue) dt = new DateTime(2000, 1, 1, 0, 0, 0);
            if (dt == DateTime.MaxValue) dt = new DateTime(2100, 1, 1, 0, 0, 0);
            buffer[offset] = (Byte)(dt.Year - 2000);
            buffer[offset + 1] = (Byte)dt.Month;
            buffer[offset + 2] = (Byte)dt.Day;
            buffer[offset + 3] = (Byte)dt.Hour;
            buffer[offset + 4] = (Byte)dt.Minute;
            buffer[offset + 5] = (Byte)dt.Second;
        }


        public static float GetFloatNumber(byte[] bytes, int offset)
        {
            if (offset > bytes.Length) return 0;
            float temp = BitConverter.ToSingle(bytes, offset);
            if (float.IsInfinity(temp) || float.IsNaN(temp))
            {
                return limit;
            }     
            if (Math.Abs(temp) > limit)
            {
                if (temp > 0)
                    return limit;
                else
                    return -limit;
            }
            return temp;
        }

        public static float GetCorrectFloatNumber(byte[] bytes, int offset)
        {
            if (offset > bytes.Length) return 0;
            float temp = FromBytesBigEndian<float>(bytes, offset);
            if (float.IsInfinity(temp) || float.IsNaN(temp))
            {
                return limit;
            }
            if (Math.Abs(temp) > limit)
            {
                if (temp > 0)
                    return limit;
                else
                    return -limit;
            }
            return temp;
        }

        private static byte[] StructToBytes(object obj)
        {
            int rawsize = Marshal.SizeOf(obj);
            IntPtr buffer = Marshal.AllocHGlobal(rawsize);
            Marshal.StructureToPtr(obj, buffer, false);
            byte[] rawdatas = new byte[rawsize];
            Marshal.Copy(buffer, rawdatas, 0, rawsize);
            Marshal.FreeHGlobal(buffer);
            return rawdatas;
        }

        private static object BytesToStruct(byte[] buf, int len, Type type)
        {
            object rtn;
            IntPtr buffer = Marshal.AllocHGlobal(len);
            Marshal.Copy(buf, 0, buffer, len);
            rtn = Marshal.PtrToStructure(buffer, type);
            Marshal.FreeHGlobal(buffer);
            return rtn;
        }

        public static int FrqToByte(int Frq)
        {
            if (Frq == 1)
            {
                return 0;
            }
            else if (Frq == 12)
            {
                return 1;
            }
            else 
            {
                return 2;
            }
        }

        public static float ByteToFrq(int Byte)
        {
            if (Byte == 0)
            {
                return 0.1f;
            }
            else if (Byte == 1)
            {
                return 1;
            }
            else if (Byte == 2)
            {
                return 12;
            }
            else
            {
                return 117;
            }

        }

        public static byte[] StringToHexByte(string hexString)
        {
            if (string.IsNullOrEmpty(hexString)) return null;
            hexString = hexString.Replace(" ", "").Replace("0x", "");
            if (string.IsNullOrEmpty(hexString)) return null;
            byte[] returnBytes = new byte[hexString.Length / 2 + hexString.Length % 2];
            for (int i = 0; i < returnBytes.Length; i++)
            {
                if (hexString.Length >= i * 2 + 2)
                    returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
                else
                    return null;
            }
            return returnBytes;
        }

    }
}
