using Panuon.WPF.UI;
using SWRIS.Core;
using SWRIS.Enums;
using SWRIS.Events;
using SWRIS.Extensions;
using SWRIS.Models;
using SWRIS.Models.ViewModel;
using System;
using System.Linq;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;

namespace SWRIS.Pages
{
    /// <summary>
    /// ParameterDialog.xaml 的交互逻辑
    /// </summary>
    public partial class ParameterDialog : WindowX
    {
        private string _serialNo;
        private Socket _clientSocket;
        private byte _runningMode = 0;
        private EquipmentSettingViewModel Equipment { get; set; }

        public ParameterDialog(EquipmentModel equipment, Socket clientSocket, RunningStatus runningStatus)
        {
            InitializeComponent();
            _serialNo = equipment.SerialNo;
            _clientSocket = clientSocket;
            _runningMode = GetRunningStatusByte(runningStatus);
            Equipment = equipment.ToEquipmentSettingViewModel(runningStatus);
            Equipment.IsConnected = _clientSocket != null && _clientSocket.Connected;
            App.TcpServer.SendGetTwistFactorData(_serialNo, _clientSocket);
            App.TcpServer.ClockResultReceived += TcpServer_ClockResultReceived;
            App.TcpServer.EncoderDirectionResultReceived += TcpServer_EncoderDirectionResultReceived;

            DataContext = Equipment;
        }

        private void TcpServer_EncoderDirectionResultReceived(object sender, EncoderDirectionResultReceivedEventArgs e)
        {
            Equipment.Parameter.EncoderDirection = e.Direction;
        }

        private void TcpServer_ClockResultReceived(object sender, ClockResultReceivedEventArgs e)
        {
            Equipment.Parameter.SystemTime = e.Timestamp.TimestampToDateTime();
        }

        protected void SetParameter()
        {
            ThreadPool.QueueUserWorkItem(act =>
            {
                EquipmentModel equipment = Equipment.ToEquipmentModel();
                if (_clientSocket != null && _clientSocket.Connected)
                {
                    EquipmentDataModel equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == equipment.IpAddress);
                    equipment.ToEquipmentDataModel(equipmentData);
                    StartOrStopDetection(equipmentData, RunningStatus.Stopped);
                    Thread.Sleep(1000);
                    App.TcpServer.SendSyncParameters(equipment.Parameter, Equipment.SerialNo, _clientSocket);
                    Thread.Sleep(300);
                    App.TcpServer.SendTurnLiveStreamData(true, _serialNo, _clientSocket);
                    Thread.Sleep(1000);
                    StartOrStopDetection(equipmentData, equipmentData.RunningStatus);

                }
                // 更新设备数据
                if (ConfigHelper.SetEquipment(equipment))
                {
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        Thread.Sleep(500);
                        NoticeBox.Show("参数设置成功", "通知", MessageBoxIcon.Success, true, 5000);
                        DialogResult = true;
                    });
                    App.UpdateEquipment(equipment);
                }
            });
        }
        private void StartOrStopDetection(EquipmentDataModel equipmentData, RunningStatus runningStatus)
        {
            byte runningMode;
            if (runningStatus.HasFlag(RunningStatus.TemporalNormal))
            {
                equipmentData.RunningStatus |= RunningStatus.PreRunning;
                runningMode = (byte)RunningStatus.TemporalNormal;
            }
            else if (runningStatus.HasFlag(RunningStatus.SpatialNormal))
            {
                equipmentData.RunningStatus |= RunningStatus.PreRunning;
                runningMode = (byte)RunningStatus.SpatialNormal;
            }
            else
            {
                equipmentData.RunningStatus |= RunningStatus.PreStop;
                runningMode = (byte)RunningStatus.Stopped;
            }

            App.TcpServer.SendStartOrStopDetection(runningMode, _serialNo, _clientSocket);
        }
        private byte GetRunningStatusByte(RunningStatus runningStatus)
        {
            // 优先级：TemporalNormal > SpatialNormal > Stopped
            if (runningStatus.HasFlag(RunningStatus.TemporalNormal))
                return (byte)RunningStatus.TemporalNormal;

            if (runningStatus.HasFlag(RunningStatus.SpatialNormal))
                return (byte)RunningStatus.SpatialNormal;

            return (byte)RunningStatus.Stopped;
        }
        protected void GetEncoderDirection()
        {
            App.TcpServer.SendGetEncoderDirectionData(_serialNo, _clientSocket);
        }
        protected void SetEncoderDirection(EncoderDirection direction)
        {
            App.TcpServer.SendSetEncoderDirectionData(direction, _serialNo, _clientSocket);
        }
        protected string GetSerialNo()
        {
            return App.Config.GenerateNewSerialNo();
        }
        private void Save_Click(object sender, RoutedEventArgs e)
        {
            SetParameter();
        }

        private void SetClockAndDirection_Click(object sender, RoutedEventArgs e)
        {
            if (Equipment.Parameter.SystemTime != null)
            {
                var systemTime = Equipment.Parameter.SystemTime.Value;
                App.TcpServer.SendSetClockData(systemTime.DateTimeToTimestamp(), _serialNo, _clientSocket);
            }
            Task.Delay(20).Wait();
            App.TcpServer.SendSetEncoderDirectionData(Equipment.Parameter.EncoderDirection, _serialNo, _clientSocket);
        }

        private void ReadClockAndDirection_Click(object sender, RoutedEventArgs e)
        {
            App.TcpServer.SendGetClockData(_serialNo, _clientSocket);
            Task.Delay(20).Wait();
            App.TcpServer.SendGetEncoderDirectionData(_serialNo, _clientSocket);
        }

        private void Clock_GotFocus(object sender, RoutedEventArgs e)
        {
            if (Equipment.Parameter.SystemTime == null)
            {
                Equipment.Parameter.SystemTime = DateTime.Now;
            }
        }

        private void SerialNo_GotFocus(object sender, RoutedEventArgs e)
        {
            if (Equipment.SerialNo.IsNullOrEmptyOrWhiteSpace())
            {
                Equipment.SerialNo = App.Config.GenerateNewSerialNo();
            }
        }

        private void SetSerialNo_Click(object sender, RoutedEventArgs e)
        {
            App.TcpServer.SendSerialNoRequest(Equipment.SerialNo, _clientSocket);
        }

        private void Upgrade_MouseDown(object sender, MouseButtonEventArgs e)
        {
            var result = MessageBoxX.Show(this, "是否确认更新设备固件？此操作将会停止设备工作。", "警告",
               MessageBoxButton.YesNo,
               MessageBoxIcon.Warning, DefaultButton.YesOK);
            if (result == MessageBoxResult.Yes)
            {
                App.TcpServer.SendUpgradeRequest(_serialNo, _clientSocket);
            }
        }

        private void RunningStatus_Click(object sender, RoutedEventArgs e)
        {
            if (sender is ToggleButton toggleButton)
            {
                if (Enum.TryParse(toggleButton.Tag.ToString(), true, out RunningStatus runningStatus))
                {
                    var newMode = GetRunningStatusByte(runningStatus);
                    if (_runningMode != newMode)
                    {
                        _runningMode = newMode;
                        StartOrStopDetection(App.DataCenter.Equipments.First(c => c.SerialNo == _serialNo), runningStatus);
                    }
                }
            }
        }
    }
}
