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

namespace AGVEmulator
{
    class DevBMS : AR.Dev.RS232
    {
        public class RequestBatteryDataArgs : EventArgs
        {

            public float Volt { get; set; }
            public float Remain { get; set; }
            public int CurA { get; set; }
            public int MaxA { get; set; }
            public UInt16 Temp1 { get; set; }
            public UInt16 Temp2 { get; set; }
            public RequestBatteryDataArgs()
            {
                this.Volt = 25;
                this.Remain = 79f;
                this.CurA = 40;
                this.MaxA = 80;
                Temp1 = 0;
                Temp2 = 0;
            }
        }
        public class RequestVoltageDataArgs : EventArgs
        {
            public UInt16[] cellVolt { get; set; }
            public RequestVoltageDataArgs()
            {

                cellVolt = new UInt16[] { 0, 0, 0, 0, 0, 0, 0, 0 };
            }
        }

        public event EventHandler<RequestBatteryDataArgs> RequestBatteryData;
        public event EventHandler<RequestVoltageDataArgs> RequestVoltageData;
        public override bool ProcessRecvData(byte[] data)
        {
            //dd로 시작하고 34개의 데이터(명령이 0D로 끝나면 34이고, 77로 끝나면 34보다크다)
            var sample000D = "DD 03 00 1B 0A 65 00 00 21 63 29 04 00 00 2C 92 00 00 00 00 00 00 28 51 03 08 02 0B 69 0B 66 FC 9C 77";
            var sampleFC77 = "DD 03 00 1B 0A 6E 0D DD 04 00 10 0D 0A 0D 09 0D 0C 0D 09 0D 0A 0D 09 0D 09 0D 0C FF 38 77 DD 04 00 10 0D 0A 0D 09 0D 0C 0D 09 0D 0A 0D 09 0D 09 0D 0C FF 38 77";
            var sampleFD77 = "DD 03 00 1B 0A 6E 00 00 1F 4A 29 04 00 4E 2C D7 00 00 00 00 00 00 28 4C 03 08 02 0B 9F 0B A9 FB A7 77 DD 03 00 1B 0A 6E 00 00 1F 4A 29 04 00 4E 2C D7 00 00 00 00 00 00 28 4C 03 08 02 0B 9F 0B AA FB A6 77";

            //basic
            var basicinfosmaple = "0A 65 00 00 21 63 29 04 00 00 2C 92 00 00 00 00 00 00 28 51 03 08 02 0B 69 0B 66";
            var basic_payload = basicinfosmaple.Split(' ').ToList().Select(t => Convert.ToByte(t, 16)).ToArray();     //old



            var barr0D = sample000D.Split(' ').ToList().Select(t => Convert.ToByte(t, 16)).ToArray();     //old
            var barrFC77 = sampleFC77.Split(' ').ToList().Select(t => Convert.ToByte(t, 16)).ToArray();   //setting
            var barrFD77 = sampleFD77.Split(' ').ToList().Select(t => Convert.ToByte(t, 16)).ToArray();   //normal

            if (data.First() != 0xDD || data.Last() != 0x77)
            {                
                RaiseMessage(MessageType.Error, $"stx,etx error data={data.HexString()}");
                return false;
            }
            var sts = data[1];
            var cmd = data[2];

            RaiseMessage(MessageType.Normal, "Rx:" + data.HexString());
            byte sendOld = 0;

            if (cmd == 0x03) //get basic info
            {
                if (RequestBatteryData != null)
                {
                    var p = new RequestBatteryDataArgs();
                    RequestBatteryData.Invoke(this, p);

                    //전압
                    var Volt = (UInt16)(p.Volt * 100);
                    var arr_volt = BitConverter.GetBytes(Volt).Reverse().ToArray();
                    Array.Copy(arr_volt, 0, basic_payload, 0, arr_volt.Length);

                    //잔량A
                    var CurA = (UInt16)p.CurA;
                    var arr_cura = BitConverter.GetBytes(CurA).Reverse().ToArray();
                    Array.Copy(arr_cura, 0, basic_payload, 4, arr_cura.Length);


                    //최대A
                    var MaxA = (UInt16)p.MaxA;
                    var arr_maxa = BitConverter.GetBytes(MaxA).Reverse().ToArray();
                    Array.Copy(arr_maxa, 0, basic_payload, 6, arr_maxa.Length);

                    //%
                    var perc = (byte)(int)p.Remain;
                    Array.Copy(new byte[] { perc }, 0, basic_payload, 19, 1);

                    //temp1
                    var temp1 = BitConverter.GetBytes((UInt16)(p.Temp1 + 2731)).Reverse().ToArray();
                    Array.Copy(temp1, 0, basic_payload, 23,2);

                    //temp2
                    var temp2 = BitConverter.GetBytes((UInt16)(p.Temp2 + 2731)).Reverse().ToArray();
                    Array.Copy(temp2, 0, basic_payload, 25, 2);

                    var datalen = (byte)basic_payload.Length;
                    var payload_cs = new List<byte>();
                    payload_cs.Add(datalen);
                    payload_cs.AddRange(basic_payload);
                    var chks = MakeCheckSum(payload_cs);

                    var buffer = new List<byte>();
                    buffer.Add(0xdd);
                    buffer.Add(cmd);
                    buffer.Add(0x00);
                    buffer.Add(datalen);
                    buffer.AddRange(basic_payload);
                    buffer.AddRange(chks);
                    buffer.Add(0x77);


                    ////makechecksum
                    //UInt16 chksum = 0;
                    //for (int i = 3; i <= 19; i++)
                    //{
                    //    chksum += barrFD77[i];
                    //}
                    //chksum = (UInt16)(0xFFFF - chksum + 1);
                    //Array.Copy(BitConverter.GetBytes(chksum).Reverse().ToArray(), 0, barrFD77, 20, 2);


                    RaiseMessage(MessageType.Normal, $"Volt:{p.Volt}v,Remain:{p.Remain}%,temp1:{p.Temp1/10f},Temp2:{p.Temp2/10f}");

                    var sendstr = System.Text.Encoding.Default.GetString(barr0D);
                    RaiseMessage(MessageType.Normal, "Tx:" + barr0D.HexString());
                    WriteData(buffer.ToArray());
                }
            }
            else if (cmd == 0x04) //get cellvoltage
            {
                if (RequestVoltageData != null)
                {
                    var p = new RequestVoltageDataArgs();
                    RequestVoltageData.Invoke(this, p);

                    //var sig = data.Skip(data.Length - 2).Take(1).First();

                    //cellvolt 240201
                    var payload = new byte[8 * 2];
                    for (int i = 0; i < 8; i++)
                    {
                        var volt = p.cellVolt[i];
                        var arr_cellvolt = BitConverter.GetBytes(volt).Reverse().ToArray();
                        Array.Copy(arr_cellvolt, 0, payload, (i * 2), arr_cellvolt.Length);
                    }

                    //makechecksum
                    var datalen = (byte)payload.Length;
                    var payload_cs = new List<byte>();
                    payload_cs.Add(datalen);
                    payload_cs.AddRange(payload);
                    var chksum = MakeCheckSum(payload_cs);

                    var buffer = new List<byte>();
                    buffer.Add(0xDD);
                    buffer.Add(cmd);
                    buffer.Add(0x00);
                    buffer.Add(datalen);
                    buffer.AddRange(payload);
                    buffer.AddRange(chksum);
                    buffer.Add(0x77);
                    WriteData(buffer.ToArray());
                    RaiseMessage(MessageType.Normal, "Tx:" + buffer.ToArray().HexString());


                }

            }




            return true;
        }
        public byte[] MakeCheckSum(IEnumerable<byte> payload)
        {
            UInt16 retval = 0;
            var payloadsum = payload.Sum(t => t);
            retval = (UInt16)(payloadsum);
            retval = (UInt16)(0xFFFF - retval);
            retval += 1;

            return BitConverter.GetBytes(retval).Reverse().ToArray();
        }
        protected override bool CustomParser(byte[] buf, out byte[] remainBuffer)
        {
            //DD A5 03 00 FF FD 77 0D
            //remainBuffer = new byte[] { };
            List<byte> remain = new List<byte>();
            bool retval = false;
            foreach (var b in buf)
            {
                if (retval)
                {
                    remain.Add(b);
                    continue;
                }

                if (b == 0xDD) //stx
                {
                    tempBuffer.Clear();
                    tempBuffer.Add(b);
                }
                else if (b == 0x0D || b == 0x77) //etx
                {
                    //과거데이터 34개이다 (DD A5 03 00 FF FD 77 0D)
                    //대쉬보드상태일때(DD A5 03 00 FF FD 77)
                    //설정상태일때-셀전압표시(DD A5 04 00 FF FC 77)

                    tempBuffer.Add(b);
                    retval = true;
                }
                else
                {
                    if (tempBuffer.Count > 0 && tempBuffer[0] == 0xDD)
                    {
                        tempBuffer.Add(b);
                        if (tempBuffer.Count > 10)
                        {
                            RaiseMessage(MessageType.Error, "buffer over");
                            tempBuffer.Clear();
                            retval = false;
                        }
                    }
                    else
                    {
                        //trash
                    }
                }
            }
            remainBuffer = remain.ToArray();
            return retval;
        }
    }
}
