using Simple3.RCS;
using Simple3.RCS.CarTypes;
using SimpleCore;
using SimpleCore.Library;
using SimpleCore.PropType;
using StandardScene.Charge;
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static SimpleCore.Traffic.TrafficControl;

namespace StandardScene.ChargeStationType
{
    public class PCBChargeStation : AbstractChargeStation
    {
        private int _index = 0;

        public int IndexReceive;
        private IPEndPoint _endPoint;

        public override void OnUdpMessage(byte[] message)
        {
            if (message != null && message.Length > 1)
                IndexReceive = message[1];
        }

        public override void CreateCommunication(IPAddress ip, int port)
        {
            _endPoint = new IPEndPoint(ip, port);
        }
        public override void SendToChargeStation(int isCharge, Car car,Site site)
        {
            var messageService = CommunicationMessageService.Instance;
            using (UdpClient udpClient = new UdpClient())
            {
                //float soc = 0f, voltage = 0, electricCurrent = 0, chargeTimeSpan = 30f;

                float setVoltage = 29.2f;
                float setElectricCurrent = 40.0f;
                float soc = 0f, voltage = 0, electricCurrent = 0, chargeTimeSpan = 30f;
                int carId = 0;
                //Site site = null;
                if (car != null)
                {
                    carId = car.id;
                    soc = (float)Commons.CarValue(car, "Soc");
                    voltage = (float)Commons.CarValue(car, "Voltage");
                    electricCurrent = (float)Commons.CarValue(car, "ElectricCurrent");
                    //site = SimpleLib.GetSite(car.status.holdingLocks.FirstOrDefault());
                   
                }
                if (site != null && site.fields.ContainsKey("setVoltage") && site.fields.ContainsKey("setElectricCurrent"))
                {
                    setVoltage = float.Parse(site.fields["setVoltage"]);
                    setElectricCurrent = float.Parse(site.fields["setElectricCurrent"]);
                }



                var msg = GetSendBytes((byte)isCharge, setVoltage, setElectricCurrent, chargeTimeSpan,
                    carId, soc, electricCurrent, voltage);
                messageService.AddSendMessage(_endPoint.Address.ToString(), _endPoint.Port, BitConverter.ToString(msg).Replace("-", " "), "FRLDShort", site?.name);
                Diagnosis.Log($"ChargeStation ADD:[{BitConverter.ToString(msg).Replace("-", " ")}]", "UDP发送报文信息", true);
                udpClient.SendAsync(msg, msg.Length, _endPoint);
                Thread.Sleep(100);
            }
        }

        private byte[] GetSendBytes(byte startCharge, float chargeVoltage, float chargeElectricCurrent, float chargeTimeSpan, int carId, float carSoc, float carElectricCurrent, float carVoltage)
        {
            var sendBytes = new byte[32];
            var indexNo = (byte)GetIndexNo();
            try
            {
                sendBytes = new byte[3] { 0xBB, indexNo, startCharge }
                    .Concat(BitConverter.GetBytes((int)chargeElectricCurrent * 10).AsEnumerable().Reverse())
                    .Concat(BitConverter.GetBytes((int)chargeVoltage * 10).AsEnumerable().Reverse())
                    .Concat(BitConverter.GetBytes((ushort)chargeTimeSpan).AsEnumerable().Reverse())
                    .Concat(BitConverter.GetBytes((ushort)carId).AsEnumerable().Reverse())
                    .Concat([(byte)carSoc])
                    .Concat(BitConverter.GetBytes((int)(carElectricCurrent * 10)).AsEnumerable().Reverse())
                    .Concat(BitConverter.GetBytes((int)(carVoltage * 10)).AsEnumerable().Reverse())
                    .Concat(new byte[] { 00, 00, 00, 00, 00, 00, 00, 0xEE }).ToArray();
                var crcCode = GetCRC(sendBytes.Skip(1).Take(28).ToArray()).AsEnumerable().Reverse().ToArray();
                sendBytes[29] = crcCode[0];
                sendBytes[30] = crcCode[1];
            }
            catch (Exception ex)
            {
                Diagnosis.Log($"充电报文组包异常 ex => {ex.Message}", "充电", true);
            }
            return sendBytes;
        }
        private byte[] GetCRC(byte[] data)
        {
            byte b = byte.MaxValue;
            byte b2 = byte.MaxValue;
            byte b3 = 1;
            byte b4 = 160;
            for (int i = 0; i < data.Length; i++)
            {
                b = (byte)(b ^ data[i]);
                for (int j = 0; j <= 7; j++)
                {
                    byte b5 = b2;
                    byte b6 = b;
                    b2 = (byte)(b2 >> 1);
                    b = (byte)(b >> 1);
                    if ((b5 & 1) == 1)
                    {
                        b = (byte)(b | 0x80u);
                    }
                    if ((b6 & 1) == 1)
                    {
                        b2 = (byte)(b2 ^ b4);
                        b = (byte)(b ^ b3);
                    }
                }
            }
            return new byte[2]
            {
                b,b2
            };
        }

        private int GetIndexNo()
        {
            if (_index < 255)
            {
                _index = _index + 1;
            }
            else
            {
                _index = 0;
            }
            return _index;
        }
    }

}
