using BPASmartClient.Helper;
using BPASmartClient.Message;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace BPASmartClient.SerialPort
{
    public class IceMakerHelper
    {

        private System.IO.Ports.SerialPort comPort = new System.IO.Ports.SerialPort();
        ConcurrentQueue<byte[]> SerialMessages = new ConcurrentQueue<byte[]>();
        public bool IsOpen => comPort.IsOpen;

        public bool Open(string portName, int baudRate)
        {
            while (!System.IO.Ports.SerialPort.GetPortNames().Contains(portName))
            {
                Thread.Sleep(1000);
            }
            while (!comPort.IsOpen)
            {
                comPort.PortName = portName;
                comPort.BaudRate = baudRate;
                comPort.DataBits = 8;
                comPort.Parity = Parity.None;
                comPort.StopBits = StopBits.One;
                comPort.ReadTimeout = 1000;
                comPort.WriteTimeout = 1000;
                //comPort.DataReceived += ComPort_DataReceived;
                comPort.RtsEnable = true;
                try
                {
                    comPort.Open();
                }
                catch (Exception ex)
                {
                    MessageLog.GetInstance.ShowEx(ex.ToString());
                    Thread.Sleep(5000);
                }
            }
            MessageLog.GetInstance.Show($"{portName} 串口打开成功");
            return comPort.IsOpen;
        }

        /*
            帧头FF	帧头FE	功能码	数据 1	数据 2	和校验	结束符
            和校验：只校验功能码和数据。=功能码+数据
            接口方式：RS485	波特率：9600

            01 查询状态指令	需要主控板定时发送查询指令，解析制冰机自检后回复的状态信息，以判断是否可以出冰。
            02 出冰指令	若制冰机状态为等待出冰，此时主控板可以发送出冰指令，以实现定量冰块输出。
            03 结束出冰指令	制冰机出冰过程中，由主控板按一定的时间发送结束指令折算时间所对应的冰量
            04 待机指令	当制冰机处于工作时，发送该指令使制冰机处于待机状态
            05 开机指令	当制冰机处于待机时，发送该指令使制冰机，制满一桶冰。
            06 抽水请求指令	预留抽水请求指令
            07 版本查询指令	品牌+硬件版本+软件版本
            09 冰量控制	通过定时开关方式控制制冰机出冰量
         */


        /// <summary>
        /// 获取制冰机状态
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public byte GetDeviceStatus()
        {
            List<int> res = new List<int>();
            byte[] buffers = new byte[7] { 0xFF, 0xFE, 0x01, 0x00, 0x00, 0x01, 0x5A };
            //发送 0xFF, 0xFE, 0x01, 0x00, 0x00, XX, 0x5A
            //返回 0xFF, 0xFD,  XX , 0x01, 0x00, XX, 0x5A 
            if (comPort.IsOpen)
            {
                comPort.Write(buffers, 0, buffers.Length);
                DateTime newDate = DateTime.Now;
                while (comPort.BytesToRead < 7)
                {
                    Thread.Sleep(1);
                    if (DateTime.Now.Subtract(newDate).TotalSeconds >= 2) break;
                }
                byte[] receive = new byte[comPort.BytesToRead];
                comPort.Read(receive, 0, receive.Length);
                if (receive.Length == 7)
                {
                    return receive[2];
                }
            }
            return default;
        }

        /// <summary>
        /// 开始制做
        /// </summary>
        /// <returns>true：开始制作</returns>
        public bool StartCook()
        {
            byte[] buffers = new byte[7] { 0xFF, 0xFE, 0x02, 0x00, 0x00, 0x02, 0x5A };
            //发送 0xFF, 0xFE, 0x02, 0x00, 0x00, XX, 0x5A 
            //返回 0xFF, 0xFD, 0x02, 0x00, 0x00, XX, 0x5A 
            if (comPort.IsOpen)
            {
                comPort.Write(buffers, 0, buffers.Length);
                while (comPort.BytesToRead < 7)
                {
                    Thread.Sleep(1);
                }
                byte[] receive = new byte[comPort.BytesToRead];
                comPort.Read(receive, 0, receive.Length);
                if (receive.Length == 7)
                    return receive[1] == 0xFD;
            }
            return false;
        }

        /// <summary>
        /// 结束制作
        /// </summary>
        /// <returns></returns>
        public bool EndCook()
        {
            byte[] buffers = new byte[7] { 0xFF, 0xFE, 0x03, 0x00, 0x00, 0x03, 0x5A };
            //发送 0xFF, 0xFE, 0x03, 0x00, 0x00, XX, 0x5A
            //返回 0xFF, 0xFD, 0x03, 0x00, 0x00, XX, 0x5A 
            if (comPort.IsOpen)
            {
                comPort.Write(buffers, 0, buffers.Length);
                while (comPort.BytesToRead < 7)
                {
                    Thread.Sleep(1);
                }
                byte[] receive = new byte[comPort.BytesToRead];
                comPort.Read(receive, 0, receive.Length);
                if (receive.Length == 7)
                    return receive[1] == 0xFD;
            }
            return false;
        }
        /// <summary>
        /// 待机
        /// </summary>
        /// <returns></returns>
        public bool Standby()
        {
            byte[] buffers = new byte[7] { 0xFF, 0xFE, 0x04, 0x00, 0x00, 0x04, 0x5A };
            //发送 0xFF, 0xFE, 0x04, 0x00, 0x00, XX, 0x5A
            //返回 0xFF, 0xFD, 0x04, 0x00, 0x00, XX, 0x5A 
            if (comPort.IsOpen)
            {
                comPort.Write(buffers, 0, buffers.Length);
                while (comPort.BytesToRead < 7)
                {
                    Thread.Sleep(1);
                }
                byte[] receive = new byte[comPort.BytesToRead];
                comPort.Read(receive, 0, receive.Length);
                if (receive.Length == 7)
                    return receive[1] == 0xFD;
            }
            return default;
        }
        /// <summary>
        /// 开机
        /// </summary>
        /// <returns></returns>
        public bool PowerOn()
        {
            byte[] buffers = new byte[7] { 0xFF, 0xFE, 0x05, 0x00, 0x00, 0x05, 0x5A };
            //发送 0xFF, 0xFE, 0x05, 0x00, 0x00, XX, 0x5A
            //返回 0xFF, 0xFD, 0x05, 0x00, 0x00, XX, 0x5A 
            if (comPort.IsOpen)
            {
                comPort.Write(buffers, 0, buffers.Length);
                while (comPort.BytesToRead < 7)
                {
                    Thread.Sleep(1);
                }
                byte[] receive = new byte[comPort.BytesToRead];
                comPort.Read(receive, 0, receive.Length);
                if (receive.Length == 6)
                    return receive[1] == 0xFD;
            }
            return default;
        }
        /// <summary>
        /// 抽水 
        /// </summary>
        /// <returns>true：允许抽水，false：不允许抽水</returns>
        public bool pump()
        {
            byte[] buffers = new byte[7] { 0xFF, 0xFE, 0x06, 0x00, 0x00, 0x06, 0x5A };
            //发送 0xFF, 0xFE, 0x04, 0x00, 0x00, XX, 0x5A
            //返回 0xFF, 0xFD, 0x04, 0x00, 0x00, XX, 0x5A 
            if (comPort.IsOpen)
            {
                comPort.Write(buffers, 0, buffers.Length);
                while (comPort.BytesToRead < 7)
                {
                    Thread.Sleep(1);
                }
                byte[] receive = new byte[comPort.BytesToRead];
                comPort.Read(receive, 0, receive.Length);
                if (receive.Length == 7)
                    return receive[3] == 0x00;
            }
            return default;
        }
        /// <summary>
        /// 冰量控制
        /// </summary>
        /// <param name="value">出冰时间 单位0.1s</param>
        /// <returns></returns>
        public bool IceValue(byte value)
        {
            byte checkNum = (byte)(0x09 + value);
            byte[] buffers = new byte[7] { 0xFF, 0xFE, 0x09, value, 0x00, checkNum, 0x5A };
            //发送 0xFF, 0xFE, 0x09, value, 0x00, XX, 0x5A
            //返回 0xFF, 0xFD, 0x09, 0x00, 0x00, XX, 0x5A 
            if (comPort.IsOpen)
            {
                comPort.Write(buffers, 0, buffers.Length);
                while (comPort.BytesToRead < 7)
                {
                    Thread.Sleep(1);
                }
                byte[] receive = new byte[comPort.BytesToRead];
                comPort.Read(receive, 0, receive.Length);
                if (receive.Length == 7)
                    return receive[3] == 0x00;
            }
            return default;
        }
    }
}
