using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using 常用工具集.Base;
using EasyModbus;
using MES.Utility.Core;
using System.Windows;
using Avalonia.Threading;

namespace 常用工具集.ViewModel._01PLC通信调试
{
    public class Modbus服务ViewModel : ViewModelBase
    {
        internal static ModbusServer server;
        public bool Enabled1 { get; set; } = true;
        public bool Enabled2 { get; set; } = false;
        public int Port { get; set; } = 502;
        private List<string> logMessageList = new List<string>();
        public string Message
        {
            get
            {
                return logMessageList.GetStrArray("\r\n");
            }
            set
            {
                NotifyPropertyChanged();
            }
        }
        public string ButtonText { get; set; } = "开启服务";

        private ushort _startAddess = 1;
        public ushort StartAddress
        {
            get { return _startAddess; }
            set
            {
                _startAddess = value;
                SetEveryList();
                NotifyPropertyChanged();
            }
        }

        public int SelectIndex1 { get; set; } = -1;
        public int SelectIndex2 { get; set; } = -1;
        public int SelectIndex3 { get; set; } = -1;
        public int SelectIndex4 { get; set; } = -1;
        public ObservableCollection<MyDataGrid> List1 { get; set; } = new ObservableCollection<MyDataGrid>();
        public ObservableCollection<MyDataGrid> List2 { get; set; } = new ObservableCollection<MyDataGrid>();
        public ObservableCollection<MyDataGrid> List3 { get; set; } = new ObservableCollection<MyDataGrid>();
        public ObservableCollection<MyDataGrid> List4 { get; set; } = new ObservableCollection<MyDataGrid>();
        public DelegateCommand StartCmd { get; set; }
        public DelegateCommand CellClickCmd { get; set; }
        public Modbus服务ViewModel()
        {
            StartCmd = new DelegateCommand(StartCmdFunc);
        }



        private void StartCmdFunc(object obj)
        {
            if (ButtonText == "开启服务")
            {
                server = new ModbusServer(Port);
                server.Start();
                //监听数据变化
                server.CoilsChanged += new ModbusServer.CoilsChangedHandler(CoilsChanged);
                server.HoldingRegistersChanged += new ModbusServer.HoldingRegistersChangedHandler(HoldingRegistersChanged);
                server.LogDataChanged += new ModbusServer.LogDataChangedHandler(LogDataChanged);
                SetEveryList();
                Enabled1 = false;
                Enabled2 = true;
                ButtonText = "停止服务";
            }
            else
            {
                logMessageList.Clear();
                Message = Guid.NewGuid().ToString();
                server.Dispose();
                server = null;
                List1.Clear(); List2.Clear(); List3.Clear(); List4.Clear();
                Enabled1 = true;
                Enabled2 = false;
                ButtonText = "开启服务";
            }
        }

        private void LogDataChanged()
        {
            Dispatcher.UIThread.Invoke(() =>
           {
               try
               {
                   logMessageList.Clear();
                   string listBoxData;
                   for (int i = 0; i < server.ModbusLogData.Length; i++)
                   {
                       if (server.ModbusLogData[i] == null)
                           break;
                       if (server.ModbusLogData[i].request)
                       {
                           listBoxData = server.ModbusLogData[i].timeStamp.ToString("H:mm:ss.ff") + " Request from Client - Functioncode: " + server.ModbusLogData[i].functionCode.ToString();
                           if (server.ModbusLogData[i].functionCode <= 4)
                           {
                               listBoxData = listBoxData + " ; Starting Address: " + server.ModbusLogData[i].startingAdress.ToString() + " Quantity: " + server.ModbusLogData[i].quantity.ToString();
                           }
                           if (server.ModbusLogData[i].functionCode == 5)
                           {
                               listBoxData = listBoxData + " ; Output Address: " + server.ModbusLogData[i].startingAdress.ToString() + " Output Value: ";
                               if (server.ModbusLogData[i].receiveCoilValues[0] == 0)
                                   listBoxData = listBoxData + "False";
                               if (server.ModbusLogData[i].receiveCoilValues[0] == 0xFF00)
                                   listBoxData = listBoxData + "True";
                           }
                           if (server.ModbusLogData[i].functionCode == 6)
                           {
                               listBoxData = listBoxData + " ; Starting Address: " + server.ModbusLogData[i].startingAdress.ToString() + " Register Value: " + server.ModbusLogData[i].receiveRegisterValues[0].ToString();
                           }
                           if (server.ModbusLogData[i].functionCode == 15)
                           {
                               listBoxData = listBoxData + " ; Starting Address: " + server.ModbusLogData[i].startingAdress.ToString() + " Quantity: " + server.ModbusLogData[i].quantity.ToString() + " Byte Count: " + server.ModbusLogData[i].byteCount.ToString() + " Values Received: ";
                               for (int j = 0; j < server.ModbusLogData[i].quantity; j++)
                               {
                                   int shift = j % 16;
                                   if ((i == server.ModbusLogData[i].quantity - 1) & (server.ModbusLogData[i].quantity % 2 != 0))
                                   {
                                       if (shift < 8)
                                           shift = shift + 8;
                                       else
                                           shift = shift - 8;
                                   }
                                   int mask = 0x1;
                                   mask = mask << (shift);
                                   if ((server.ModbusLogData[i].receiveCoilValues[j / 16] & (ushort)mask) == 0)
                                       listBoxData = listBoxData + " False";
                                   else
                                       listBoxData = listBoxData + " True";
                               }
                           }
                           if (server.ModbusLogData[i].functionCode == 16)
                           {
                               listBoxData = listBoxData + " ; Starting Address: " + server.ModbusLogData[i].startingAdress.ToString() + " Quantity: " + server.ModbusLogData[i].quantity.ToString() + " Byte Count: " + server.ModbusLogData[i].byteCount.ToString() + " Values Received: ";
                               for (int j = 0; j < server.ModbusLogData[i].quantity; j++)
                               {
                                   listBoxData = listBoxData + " " + server.ModbusLogData[i].receiveRegisterValues[j];
                               }
                           }
                           if (server.ModbusLogData[i].functionCode == 23)
                           {
                               listBoxData = listBoxData + " ; Starting Address Read: " + server.ModbusLogData[i].startingAddressRead.ToString() + " ; Quantity Read: " + server.ModbusLogData[i].quantityRead.ToString() + " ; Starting Address Write: " + server.ModbusLogData[i].startingAddressWrite.ToString() + " ; Quantity Write: " + server.ModbusLogData[i].quantityWrite.ToString() + " ; Byte Count: " + server.ModbusLogData[i].byteCount.ToString() + " ; Values Received: ";
                               for (int j = 0; j < server.ModbusLogData[i].quantityWrite; j++)
                               {
                                   listBoxData = listBoxData + " " + server.ModbusLogData[i].receiveRegisterValues[j];
                               }
                           }

                           logMessageList.Add(listBoxData);
                       }
                       if (server.ModbusLogData[i].response)
                       {
                           if (server.ModbusLogData[i].exceptionCode > 0)
                           {
                               listBoxData = server.ModbusLogData[i].timeStamp.ToString("H:mm:ss.ff");
                               listBoxData = listBoxData + (" Response To Client - Error code: " + Convert.ToString(server.ModbusLogData[i].errorCode, 16));
                               listBoxData = listBoxData + " Exception Code: " + server.ModbusLogData[i].exceptionCode.ToString();
                               logMessageList.Add(listBoxData);


                           }
                           else
                           {
                               listBoxData = (server.ModbusLogData[i].timeStamp.ToString("H:mm:ss.ff") + " Response To Client - Functioncode: " + server.ModbusLogData[i].functionCode.ToString());

                               if (server.ModbusLogData[i].functionCode <= 4)
                               {
                                   listBoxData = listBoxData + " ; Bytecount: " + server.ModbusLogData[i].byteCount.ToString() + " ; Send values: ";
                               }
                               if (server.ModbusLogData[i].functionCode == 5)
                               {
                                   listBoxData = listBoxData + " ; Starting Address: " + server.ModbusLogData[i].startingAdress.ToString() + " ; Output Value: ";
                                   if (server.ModbusLogData[i].receiveCoilValues[0] == 0)
                                       listBoxData = listBoxData + "False";
                                   if (server.ModbusLogData[i].receiveCoilValues[0] == 0xFF00)
                                       listBoxData = listBoxData + "True";
                               }
                               if (server.ModbusLogData[i].functionCode == 6)
                               {
                                   listBoxData = listBoxData + " ; Starting Address: " + server.ModbusLogData[i].startingAdress.ToString() + " ; Register Value: " + server.ModbusLogData[i].receiveRegisterValues[0].ToString();
                               }
                               if (server.ModbusLogData[i].functionCode == 15)
                               {
                                   listBoxData = listBoxData + " ; Starting Address: " + server.ModbusLogData[i].startingAdress.ToString() + " ; Quantity: " + server.ModbusLogData[i].quantity.ToString();
                               }
                               if (server.ModbusLogData[i].functionCode == 16)
                               {
                                   listBoxData = listBoxData + " ; Starting Address: " + server.ModbusLogData[i].startingAdress.ToString() + " ; Quantity: " + server.ModbusLogData[i].quantity.ToString();
                               }
                               if (server.ModbusLogData[i].functionCode == 23)
                               {
                                   listBoxData = listBoxData + " ; ByteCount: " + server.ModbusLogData[i].byteCount.ToString() + " ; Send Register Values: ";
                               }
                               if (server.ModbusLogData[i].sendCoilValues != null)
                               {
                                   for (int j = 0; j < server.ModbusLogData[i].sendCoilValues.Length; j++)
                                   {
                                       listBoxData = listBoxData + server.ModbusLogData[i].sendCoilValues[j].ToString() + " ";
                                   }
                               }
                               if (server.ModbusLogData[i].sendRegisterValues != null)
                               {
                                   for (int j = 0; j < server.ModbusLogData[i].sendRegisterValues.Length; j++)
                                   {
                                       listBoxData = listBoxData + server.ModbusLogData[i].sendRegisterValues[j].ToString() + " ";
                                   }
                               }
                               logMessageList.Add(listBoxData);
                           }
                       }
                   }
               }
               catch (Exception) { }
               Message = Guid.NewGuid().ToString();
           });

        }



        private void SetEveryList()
        {
            ushort startAddress = StartAddress;
            List1.Clear();
            for (int i = startAddress; i < 10 + startAddress; i++)
            {
                MyDataGrid data = new MyDataGrid { Which = 1, Address = i, Value1 = server.coils[i + 1] };

                if (server.coils[i + 1])
                {
                    data.Color = "Green";
                }
                else
                {
                    data.Color = "Red";
                }
                List1.Add(data);
            }

            List2.Clear();
            for (int i = startAddress; i < 10 + startAddress; i++)
            {
                MyDataGrid data = new MyDataGrid { Which = 2, Address = i, Value1 = server.discreteInputs[i + 1] };
                if (server.discreteInputs[i + 1])
                {
                    data.Color = "Green";
                }
                else
                {
                    data.Color = "Red";
                }
                List2.Add(data);
            }

            List3.Clear();
            for (int i = startAddress; i < 10 + startAddress; i++)
            {
                MyDataGrid data = new MyDataGrid { Which = 3, Address = i, Value2 = server.holdingRegisters[i + 1] };
                List3.Add(data);
            }

            List4.Clear();
            for (int i = startAddress; i < 10 + startAddress; i++)
            {
                MyDataGrid data = new MyDataGrid { Which = 4, Address = i, Value2 = server.inputRegisters[i + 1] };
                List4.Add(data);
            }
        }

        private void HoldingRegistersChanged(int register, int numberOfRegisters)
        {
           Dispatcher.UIThread.Invoke(() => { SetEveryList(); });
        }

        private void CoilsChanged(int coil, int numberOfCoils)
        {
            Dispatcher.UIThread.Invoke(() => { SetEveryList(); });
        }

    }

    public class MyDataGrid : ViewModelBase
    {
        public int Which { get; set; }
        public int Address { get; set; }

        public bool Value1 { get; set; }
        public ushort Value2 { get; set; }
        public string Color { get; set; }
    }
}