using System.ComponentModel.DataAnnotations;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Models;

namespace JiShe.CollectBus.Common.Extensions
{
    public static class HexStringExtensions
    {
        //起始字符
        private const string startStr = "68";
        //结束字符
        private const string endStr = "16";
        //头部字节长度
        private const int hearderLen = 6;
        //消息认证码字段长度
        private const int pWLen = 16;

        private const int FixedLength = 18;

       
        public static object GetAnalyzeValue(this List<string> hexStringList, CommandChunkEnum chunk) 
        {
            if (hexStringList.Count < hearderLen || hexStringList[0] != startStr || hexStringList[5] != startStr || hexStringList.Count < FixedLength)
            {
                return null;
            }

            switch (chunk)
            {              
                case CommandChunkEnum.AFN:
                    var aFn = hexStringList[(int)CommandChunkEnum.AFN].HexToDec();//1字节
                    return aFn;
                case CommandChunkEnum.FN:
                    //(DT2*8)+DT1=fn
                    var dt1Bin = hexStringList[(int)CommandChunkEnum.FN - 1].HexToBin();
                    var dt1 = dt1Bin != "0" ? dt1Bin.Length : 0;
                    var dt2 = hexStringList[(int)CommandChunkEnum.FN].HexToDec();
                    var fn = dt2 * 8 + dt1;
                    return fn;
                case CommandChunkEnum.A:
                    var aHexList = hexStringList.Skip((int)CommandChunkEnum.A).Take(5).ToList();
                    var a1 = aHexList[1] + aHexList[0];
                    var a2 = aHexList[3] + aHexList[2];
                    var a2Dec = a2.HexToDec();
                    var a3 = aHexList[4];
                    var a = $"{a1}{a2Dec.ToString().PadLeft(5, '0')}";
                    var a3Bin = aHexList[4].HexToBin().PadLeft(8, '0');
                    var msa = a3Bin.Substring(0, 7).BinToDec();
                    return new Tuple<string,int>(a, msa);
                case CommandChunkEnum.SEQ:
                    var seq = hexStringList[(int)CommandChunkEnum.SEQ].HexToBin().PadLeft(8, '0');
                    var tpV = (TpV)Convert.ToInt32(seq.Substring(0, 1));
                    var firfin = (FIRFIN)Convert.ToInt32(seq.Substring(1, 2));
                    var con = (CON)Convert.ToInt32(seq.Substring(3, 1));
                    var prseqBin = seq.Substring(4, 4);
                    return new Seq
                    {
                        CON = con,
                        FIRFIN = firfin,
                        PRSEQ = prseqBin.BinToDec(),
                        TpV = tpV
                    };
                case CommandChunkEnum.Data:                   
                    var lenIndex = (int)CommandChunkEnum.Len;
                    var lenBin = (hexStringList[lenIndex + 1]+hexStringList[lenIndex]).HexToBin();                  
                    var len = lenBin.Remove(lenBin.Length - 2).BinToDec();

                    //验证长度 2=(帧校验和+结束字符）
                    if (hexStringList.Count - 2 != hearderLen + len)
                        return null;

                    var dataHexList = hexStringList.Skip(FixedLength).Take(len + hearderLen - FixedLength).ToList();
                    return dataHexList;
                default:
                    throw new ArgumentOutOfRangeException(nameof(chunk), chunk, null);
            }
        }

        public static bool IsStartStr(this string str)
        {
            return str == startStr ? true : false;
        }

        /// <summary>
        /// 字节加33
        /// </summary>
        /// <param name="hexStringList"></param>
        /// <returns></returns>
        public static List<string> AddHex33(this List<string> hexStringList)
        {
            for (int i = 0; i < hexStringList.Count; i++)
            {
                hexStringList[i] = (Convert.ToInt32(hexStringList[i], 16) + Convert.ToInt32("33", 16)).ToString("X2");
                if (hexStringList[i].Length > 2)
                {
                    hexStringList[i] = hexStringList[i].Substring(hexStringList[i].Length - 2);
                }
            }

            return hexStringList;
        }

        public static List<string> ReduceHex33(this List<string> hexStringList)
        {
            for (int i = 0; i < hexStringList.Count; i++)
            {
                var value = Convert.ToInt32(hexStringList[i], 16) - Convert.ToInt32("33", 16);
                hexStringList[i] = value.DecToHex().PadLeft(2, '0');
            }

            return hexStringList;
        }

        public static string GetCRC(List<string> inputFrm, int startIndex = 0)
        {
            int sum = 0;
            for (int i = startIndex; i < inputFrm.Count; i++)
            {
                sum += (Convert.ToInt32(inputFrm[i], 16));
            }
            var sum16 = Convert.ToString(sum, 16);
            return sum16.Substring(sum16.Length - 2, 2).ToUpper();
        }

        public static byte[] GetCRC16(byte[] data, bool isReverse = false)
        {
            int len = data.Length;
            if (data == null || data.Length == 0) return new byte[] { 0, 0 };

            ushort crc = 0xFFFF;
            for (int i = 0; i < len; i++)
            {
                crc = (ushort)(crc ^ (data[i]));
                for (int j = 0; j < 8; j++)
                {
                    crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
                }
            }
            byte hi = (byte)((crc & 0xFF00) >> 8); //高位置
            byte lo = (byte)(crc & 0x00FF); //低位置
            if (isReverse) return new byte[] { lo, hi };
            return new byte[] { hi, lo };
        }
    }


   


}
