using SuperSocket.ProtoBase;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Waste.Socket
{
    public class MyPackageFilter : FixedHeaderPipelineFilter<MyPackage>
    {
        /// <summary>
        /// Header size is 2
        /// </summary>
        public MyPackageFilter()
            : base(2) //包头的大小是2字节，所以将2传如基类的构造方法中去
        {

        }
        /// <summary>
        /// 从数据包的头部返回包体的大小
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        protected override int GetBodyLengthFromHeader(ref ReadOnlySequence<byte> buffer)
        {
            int len = 0;
            var reader = new SequenceReader<byte>(buffer);
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            string key = reader.ReadString(Encoding.GetEncoding("GB2312"));
            if (key != "A9")
            {

            }
            else
            {
                len = (int)buffer.Length - 2;
            }
            return len;
        }
        /// <summary>
        /// 将数据包解析成 MyPackage 的实例
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        protected override MyPackage DecodePackage(ref ReadOnlySequence<byte> buffer)
        {
            var package = new MyPackage();
            var reader = new SequenceReader<byte>(buffer);
            var _reader = reader;
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            package.Str = Tools.GetString(buffer);
            reader.TryRead(out byte keyByte);
            string key = keyByte.ByteToHexStr();
            if (key != "A9")
            {
                var len = buffer.Length;
                string msg = key;
                for (var i = 1; i < len; i++)
                {
                    reader.TryRead(out byte msgByte);
                    msg += msgByte.ByteToHexStr();
                }
                package.IsChecked = false;
                package.Body = msg;
            }
            else
            {
                package.Key = key;
                package.Len = (int)buffer.Length - 2;
                string body = "";
                byte[] bytes = new byte[package.Len];
                for (var i = 0; i < package.Len; i++)
                {
                    reader.TryRead(out byte val);
                    bytes[i] = val;
                }
                if (bytes.Length == 1 && bytes[0] == 0)
                {
                    return null;
                }
                Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
                body = bytes.BytesToString().Replace("\n", "").Replace("\r", "");
                package.Body = body;
                var arr = body.Split('|');
                #region 心跳包的处理,IMEI|GPS
                if (arr.Length == 2)
                {
                    package.IsHeart = true;
                    package.IMEI = arr[0];
                    var gpsarr = arr[1].Split(',');
                    if (gpsarr.Length == 2)
                    {
                        package.Longitude = gpsarr[0];
                        package.Latitude = gpsarr[1];
                    }
                }
                else if (arr.Length == 7)
                {
                    package.ICCID = arr[0];
                    package.IMEI = arr[1];
                    package.IMSI = arr[2];
                    package.GSLQ = arr[3];
                    package.Time = $"{arr[4]}{arr[5]}";
                    //九方城@前门@厨余垃圾@7.91
                    var measurearr = arr[6].Split('@');
                    if (measurearr.Length == 4)
                    {
                        package.City = measurearr[0];
                        package.Area = measurearr[1];
                        package.WasteType = measurearr[2];
                        package.Weight = measurearr[3];
                    }
                }
                #endregion
            }
            return package;
        }
    }
    /// <summary>
    /// 转换工具
    /// </summary>
    public static class Tools
    {
        public static string GetString(in this ReadOnlySequence<byte> payload,
    Encoding encoding = null)
        {
            encoding ??= Encoding.UTF8;
            return payload.IsSingleSegment ? encoding.GetString(payload.FirstSpan)
                : GetStringSlow(payload, encoding);

            static string GetStringSlow(in ReadOnlySequence<byte> payload, Encoding encoding)
            {
                // linearize
                int length = checked((int)payload.Length);
                var oversized = ArrayPool<byte>.Shared.Rent(length);
                try
                {
                    payload.CopyTo(oversized);
                    return encoding.GetString(oversized, 0, length);
                }
                finally
                {
                    ArrayPool<byte>.Shared.Return(oversized);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bt"></param>
        /// <returns></returns>
        public static string ByteToHexStr(this byte bt)
        {
            return ((int)bt).ToString("X2");
        }
        /// <summary>
        /// byte转int
        /// </summary>
        /// <param name="bt"></param>
        /// <returns></returns>
        public static int ByteToInt(this byte bt)
        {
            return Convert.ToInt32(((int)bt).ToString("X2"), 16);
        }
        /// <summary>
        /// 字节数组转16进制
        /// </summary>
        /// <param name="bt"></param>
        /// <returns></returns>
        public static string BytesToHexStr(this byte[] bt)
        {
            string returnStr = "";
            if (bt != null)
            {
                for (int i = 0; i < bt.Length; i++)
                {
                    returnStr += bt[i].ToString("X2") + " ";
                }
            }
            return returnStr;
        }
        /// <summary>
        /// 字节数组转字符串
        /// </summary>
        /// <param name="bt"></param>
        /// <returns></returns>
        public static string BytesToString(this byte[] bytes)
        {
            string returnStr = "";
            if (bytes != null)
            {
                returnStr = Encoding.GetEncoding("GB2312").GetString(bytes);
            }
            return returnStr;
        }
        /// <summary>
        /// 字节数据转中文
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string BytesToChsString(this byte[] bytes)
        {
            string hex = BytesToHexStr(bytes);
            if (hex == null)
                return "";
            if (hex.Length % 2 != 0)
            {
                hex += "20";//空格
            }
            for (int i = 0; i < bytes.Length; i++)
            {
                try
                {
                    // 每两个字符是一个 byte。
                    bytes[i] = byte.Parse(hex.Substring(i * 2, 2),
                        System.Globalization.NumberStyles.HexNumber);
                }
                catch
                {
                }
            }
            // 获得 GB2312，Chinese Simplified。
            Encoding chs = Encoding.GetEncoding("gb2312");
            return chs.GetString(bytes);
        }

    }
    /// <summary>
    /// 垃圾分类格式解析,传输过来的数据格式类似于:九方城@前门@厨余垃圾@7.91
    /// </summary>
    public class WastePackageFilter : PipelineFilterBase<MyPackage>
    {
        public override MyPackage Filter(ref SequenceReader<byte> reader)
        {
            try
            {
                if(reader.Length <= 0)
                {
                    return null;
                }
                var package = new MyPackage();
                var _reader = reader;
                Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
                package.Str = _reader.ReadString(Encoding.GetEncoding("GB2312"));
                string key = "";
                int keylen = 1;
                #region 解析头部，头部固定为A9
                if(reader.Length >= 2)
                {
                    keylen = 2;
                    byte[] keys = new byte[2];
                    reader.TryRead(out byte key1Byte);
                    keys[0] = key1Byte;
                    reader.TryRead(out byte key2Byte);
                    keys[1] = key2Byte;
                    key = keys.BytesToString();
                }
                else
                {
                    byte[] keys = new byte[1];
                    reader.TryRead(out byte key1Byte);
                    keys[0] = key1Byte;
                    key = keys.BytesToString();
                }
                #endregion
                if (key != "A9")
                {
                    var len = reader.Length;
                    string msg = "";
                    reader.Rewind(keylen);
                    for (var i = 0; i < len; i++)
                    {
                        reader.TryRead(out byte msgByte);
                        msg += msgByte.ByteToHexStr();
                    }
                    package.IsChecked = false;
                    package.Body = msg;
                }
                else
                {
                    package.Key = key;
                    package.Len = (int)reader.Length - 2;
                    string body = "";
                    byte[] bytes = new byte[package.Len];
                    for (var i = 0; i < package.Len; i++)
                    {
                        reader.TryRead(out byte val);
                        bytes[i] = val;
                    }
                    if (bytes.Length == 1 && bytes[0] == 0)
                    {
                        return null;
                    }
                    body = bytes.BytesToString().Replace("\r", "").Replace("\n", "");
                    package.Body = bytes.BytesToHexStr();
                    var arr = body.Split('|');
                    #region 心跳包的处理,IMEI|GPS
                    if (arr.Length == 2)
                    {
                        package.IsHeart = true;
                        package.IMEI = arr[0];
                        var gpsarr = arr[1].Split(',');
                        if (gpsarr.Length == 2)
                        {
                            package.Longitude = gpsarr[0];
                            package.Latitude = gpsarr[1];
                        }
                    }
                    else if (arr.Length == 7)
                    {
                        package.ICCID = arr[0];
                        package.IMEI = arr[1];
                        package.IMSI = arr[2];
                        var gslq = Encoding.GetEncoding("GB2312").GetBytes(arr[3]);
                        if(gslq.Length == 2)
                        {
                            package.GSLQ = Convert.ToInt32(gslq[1]).ToString();
                        }
                        else
                        {
                            package.GSLQ = gslq.BytesToHexStr();
                        }
                        package.Time = $"{arr[4]}{arr[5]}".Replace("-","").Replace(":","");
                        //九方城@前门@厨余垃圾@7.91
                        var measurearr = arr[6].Split('@');
                        if (measurearr.Length == 4)
                        {
                            package.City = measurearr[0];
                            package.Area = measurearr[1];
                            package.WasteType = measurearr[2];
                            package.Weight = measurearr[3];
                            package.IsWeight = true;
                        }
                        else
                        {
                            package.City = arr[6];//临时存放传递过来的数据
                        }
                    }
                    #endregion
                }
                return package;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"数据处理发生异常:{ex.Message}");
                return new MyPackage();
            }
        }
    }
}
