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

namespace GatewayTool.Protocols
{
    public class GatewayProtocolBase
    {
        public static readonly byte[] head = { 0xee };
        public static readonly byte[] tail = { 0xbb };

        public byte[] Pack(byte[] data)
        {
            byte[] ret = { };
            byte[] crc16 = { };

            crc16 = CRC16.GetCRC(data);

            ret = ret.Concat(head).ToArray();
            ret = ret.Concat(data).ToArray();
            ret = ret.Concat(crc16).ToArray();
            ret = ret.Concat(tail).ToArray();

            return ret;
        }

        public byte[] PackJson(byte[] data, string json)
        {
            byte[] ret = { };
            byte[] crc16 = { };

            crc16 = CRC16.GetCRC(data);

            ret = ret.Concat(head).ToArray();
            ret = ret.Concat(data).ToArray();
            ret = ret.Concat(crc16).ToArray();
            ret = ret.Concat(tail).ToArray();

            byte[] bytes = Encoding.ASCII.GetBytes(json);
            ret = ret.Concat(bytes).ToArray();

            return ret;
        }

        public byte[] Unpack(byte[] data)
        {
            int length = data.Length;
            if (data[0] == head[0] && data[length - 1] == tail[0])  //a pkg is finished
            {
                //skip pkg's head and tail
                int head = 1;
                int tail = length - 1;
                int i = 0;
                byte[] pkg = new byte[length - 2];

                for (int a = head; a < tail; a++)
                {
                    pkg[i++] = data[a];
                }

                if (CRC16.CheckCRC(pkg))
                {
                    byte[] data2 = pkg.Skip(1).Take(pkg.Length - 3).ToArray(); //remove function code & crc data                    
                    return data2;
                }
            }
            return null;
        }

        public byte[] PackSniffDevice()
        {
            byte[] data = { 0x01 };
            return Pack(data);
        }

        public SniffReplyInfo UnpackSniff(byte[] data)
        {
            byte[] data2 = Unpack(data);
            return ProcessFindingDevice(data2);
        }

        private SniffReplyInfo ProcessFindingDevice(byte[] pkg)
        {
            if (pkg == null || pkg.Length == 0) return null;
            SniffReplyInfo info = null;
            string message = Encoding.ASCII.GetString(pkg, 0, pkg.Length);

            if (message.Contains(";"))
            {
                string[] strArray = message.Split(';');
                info = new SniffReplyInfo();

                for (int index = 0; index < strArray.Length; index++)
                {
                    switch (index)
                    {
                        case 0:
                            info.SN = strArray[index];
                            break;
                        case 1:
                            info.Version = strArray[index];
                            break;
                        default:
                            break;
                    }
                }
            }

            return info;
        }
    }
}