using MES.Utility.Core;
using SerialDebug;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using 常用工具集.Base;
using 常用工具集.Utility.Network;
using static EasyModbus.TCPHandler;

namespace 常用工具集.ViewModel._01PLC通信调试
{
    public class Socket调试ViewModel : ViewModelBase
    {
        private System.IO.Ports.SerialPort serialPort;
        public bool Enabled1 { get; set; } = true;
        public bool Enabled2 { get; set; } = false;
        public string ButtonText { get; set; } = "打开";

        public string IpAddress { get; set; } = "127.0.0.1";
        public int Port { get; set; } = 502;
        public int Timeout { get; set; } = 1000;

        public bool ReciveASCChecked { get; set; } = true;
        public bool ReciveHexChecked { get; set; } = false;


        public bool SendASCChecked { get; set; } = true;
        public bool SendHexChecked { get; set; } = false;
        public bool ConvertChecked { get; set; } = true;
        public bool CycleChecked { get; set; } = false;
        public int CycleTime { get; set; } = 1000;


        public string SendContent { get; set; } = "";

        private object _lock = new object();
        private List<string> msgList = new List<string>();
        public string Message
        {
            get
            {
                lock (_lock)
                {
                    return msgList.GetStrArray("\r\n");
                }
            }
            set
            {
                NotifyPropertyChanged();
            }
        }

        public DelegateCommand OpenSerialCmd { get; set; }
        public DelegateCommand ClearReciveCmd { get; set; }
        public DelegateCommand ClearSendCmd { get; set; }
        public DelegateCommand SendCmd { get; set; }

        private TcpClient client;
        private Stream stream;
        private Thread sendThread;
        public Thread readThread;

        public Socket调试ViewModel()
        {
            serialPort = new SerialPort();
            //打开关闭串口
            OpenSerialCmd = new DelegateCommand(OpenSerialCmdFunc);
            ClearReciveCmd = new DelegateCommand(ClearReciveCmdFunc);
            ClearSendCmd = new DelegateCommand(ClearSendCmdFunc);
            SendCmd = new DelegateCommand(SendCmdFunc);
        }

        private void OpenSerialCmdFunc(object obj)
        {
            try
            {
                if (ButtonText == "打开")
                {
                    client = new TcpClient();
                    IAsyncResult asyncResult = client.BeginConnect(IpAddress, Port, null, null);
                    if (!asyncResult.AsyncWaitHandle.WaitOne(Timeout))
                    {
                        GlobalValues.Error("连接超时");
                        return;
                    }
                    client.EndConnect(asyncResult);
                    stream = client.GetStream();
                    ButtonText = "关闭";
                    Enabled1 = false;
                    Enabled2 = true;
                    readThread = new Thread(ReadThread);
                    readThread.Start();
                }
                else
                {
                    sendThread?.Interrupt();
                    sendThread = null;
                    readThread.Interrupt();
                    readThread = null;
                    stream.Close();
                    client.Close();
                    client.Dispose();
                    client = null;
                    ButtonText = "打开";
                    Enabled1 = true;
                    Enabled2 = false;
                }
            }
            catch (Exception ex)
            {
                client.Close();
                client = null;
                GlobalValues.Error(ex.Message);
            }
        }



        private void ClearReciveCmdFunc(object obj)
        {
            lock (_lock)
            {
                msgList.Clear();
            }
            Message = Guid.NewGuid().ToString();
        }

        private void ClearSendCmdFunc(object obj)
        {
            SendContent = string.Empty;
        }

        private void SendCmdFunc(object obj)
        {
            try
            {

                if (sendThread != null)
                {
                    GlobalValues.Error("正在执行循环周期发送,不能发送数据");
                    return;
                }
                if (SendContent.IsNullOrEmpty())
                {
                    GlobalValues.Error("没有任何可发送的数据");
                    return;
                }
                //要发送的数据 
                SendParamFormat format = SendParamFormat.ASCII;
                if (SendHexChecked)
                {
                    format = SendParamFormat.Hex;
                }
                int sendInterval = Convert.ToInt32(CycleTime);
                CSendParam param = new CSendParam(format, SendParamMode.SendAfterLastSend, sendInterval, SendContent, ConvertChecked);

                if (CycleChecked)
                {
                    sendThread = new Thread(SendThread);
                    sendThread.Start(param);
                }
                else
                {
                    SendData(param);
                }

            }
            catch (Exception ex)
            {
                GlobalValues.Error(ex.Message);
            }
        }



        private void sp_SendCompletedEvent(object sender, SendCompletedEventArgs e)
        {
            if (e.SendParam == null)
            {
                GlobalValues.Error("发送失败");
                OpenSerialCmdFunc(null);
                return;
            }
            lock (_lock)
            {
                msgList.Add($"{e.TimeString}[-->]");
                if (SendASCChecked)
                {
                    msgList.Add(e.SendParam.ASCIIString);
                }
                else
                {
                    msgList.Add(e.SendParam.HexString);
                }
                if (msgList.Count > 300)
                {
                    int cha = msgList.Count - 300;
                    //lines.Reverse();
                    //差多少，删多少
                    for (int i = 0; i < cha; i++)
                    {
                        msgList.RemoveAt(0);
                    }
                }
            }
            Message = Guid.NewGuid().ToString();
        }

        /// <summary>
        /// 接收事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void sp_ReceivedEvent(object sender, SerialDebugReceiveData e)
        {
            if (e != null)
            {
                lock (_lock)
                {
                    msgList.Add($"{e.TimeString}[<--]");
                    if (ReciveASCChecked)
                    {
                        msgList.Add(e.ASCIIString);
                    }
                    else
                    {
                        msgList.Add(e.HexString);
                    }
                    if (msgList.Count > 300)
                    {
                        int cha = msgList.Count - 300;
                        //lines.Reverse();
                        //差多少，删多少
                        for (int i = 0; i < cha; i++)
                        {
                            msgList.RemoveAt(0);
                        }
                    }
                }
                Message = Guid.NewGuid().ToString();
            }
        }


        void sp_SendOverEvent(object sender, EventArgs e)
        {
        }




        private void ReadThread(object obj)
        {
            while (true)
            {
                try
                {
                    var available = client.Available;
                    if (available > 0)
                    {
                        byte[] bytes = new byte[available];
                        stream.Read(bytes, 0, bytes.Length);
                        SerialDebugReceiveData data = new SerialDebugReceiveData(bytes);
                        lock (_lock)
                        {
                            msgList.Add($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}[<--]");
                            if (ReciveASCChecked)
                            {
                                msgList.Add(data.ASCIIString);
                            }
                            else
                            {
                                msgList.Add(data.HexString);
                            }
                            if (msgList.Count > 300)
                            {
                                int cha = msgList.Count - 300;
                                //lines.Reverse();
                                //差多少，删多少
                                for (int i = 0; i < cha; i++)
                                {
                                    msgList.RemoveAt(0);
                                }
                            }
                        }
                        Message = Guid.NewGuid().ToString();
                    }
                    Thread.Sleep(1);
                }
                catch (ThreadInterruptedException ex)
                {
                    break;
                }
                catch (Exception ex)
                {

                }
            }
        }

        private void SendData(CSendParam param)
        {
            try
            {
                stream.Write(param.DataBytes, 0, param.DataBytes.Length);
                lock (_lock)
                {
                    msgList.Add($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}[<--]");
                    if (ReciveASCChecked)
                    {
                        msgList.Add(param.ASCIIString);
                    }
                    else
                    {
                        msgList.Add(param.HexString);
                    }
                    if (msgList.Count > 300)
                    {
                        int cha = msgList.Count - 300;
                        //lines.Reverse();
                        //差多少，删多少
                        for (int i = 0; i < cha; i++)
                        {
                            msgList.RemoveAt(0);
                        }
                    }
                }
                Message = Guid.NewGuid().ToString();
            }
            catch (Exception ex)
            {
            }

        }

        private void SendThread(object obj)
        {
            CSendParam parm = (CSendParam)obj;
            while (true)
            {
                try
                {
                    SendData(parm);
                    Thread.Sleep(CycleTime);
                }
                catch (ThreadInterruptedException ex)
                {
                    break;
                }
                catch (Exception ex)
                {

                }
            }
        }
    }
}