using BOB.Models;
using BOB.Singleton;
using BOB.Views.Dialogs;
using Common.PubEvent;
using DeviceCommand.Base;
using DeviceCommand.Device;
using Logger;
using MaterialDesignThemes.Wpf;
using Model;
using OxyPlot;
using Prism.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Xml;

namespace BOB.ViewModels
{
    public class ParametersManagerViewModel:BindableBase
    {
        #region 属性
        private ObservableCollection<DeviceConfigModel> _DeviceList;

        public ObservableCollection<DeviceConfigModel> DeviceList
        {
            get { return _DeviceList; }
            set { SetProperty(ref _DeviceList,value); }
        }
        private ObservableCollection<DeviceInfoModel> _DeviceInfoModel;

        public ObservableCollection<DeviceInfoModel> DeviceInfoModel
        {
            get { return _DeviceInfoModel; }
            set { SetProperty(ref _DeviceInfoModel, value); }
        }

        public ProgramModel Program
        {
            get => _globalVariables.Program;
            set
            {
                if (_globalVariables.Program != value)
                {
                    _globalVariables.Program = value;
                    RaisePropertyChanged();
                }
            }
        }
        private ParameterModel _SelectedParameter;
        public ParameterModel SelectedParameter
        {
            get => _SelectedParameter;
            set
            {
                if (SetProperty(ref _SelectedParameter, value))
                {
                    _globalVariables.SelectedParameter = value;
                }
            }
        }
        private DeviceInfoModel _SelectedDevice;
        public DeviceInfoModel SelectedDevice
        {
            get { return _SelectedDevice; }
            set { SetProperty(ref _SelectedDevice, value); }
        }
        #endregion
        private GlobalVariables _globalVariables { get; set; }
        private IDialogService _dialogService { get; set; }
        private IContainerProvider _containerProvider { get; set; }
        private Devices _devices { get; set; }
        private IEventAggregator _eventAggregator { get; set; }
        public ICommand ParameterAddCommand { get; set; }
        public ICommand ParameterEditCommand { get; set; }
        public ICommand ParameterDeleteCommand { get; set; }
        public ICommand DeviceEditCommand { get; set; }
        public ICommand ReconnnectCommand { get; set; }
        public ICommand CloseCommand { get; set; }
       
  

        public ParametersManagerViewModel(GlobalVariables GlobalVariables,IDialogService dialogService,IEventAggregator eventAggregator,IContainerProvider containerProvider)
        {
            _containerProvider= containerProvider;  
            _globalVariables = GlobalVariables;
            _eventAggregator= eventAggregator;
            _devices=containerProvider.Resolve<Devices>();
            _dialogService = dialogService;
            Program = _globalVariables.Program;
            ParameterAddCommand = new DelegateCommand(ParameterAdd);
            ParameterEditCommand = new DelegateCommand(ParameterEdit);
            ParameterDeleteCommand = new DelegateCommand(ParameterDelete);
            DeviceEditCommand = new DelegateCommand(DeviceEdit);
            ReconnnectCommand = new DelegateCommand(Reconnnect);
            CloseCommand = new DelegateCommand(Close);
            DeviceList = new ObservableCollection<DeviceConfigModel>(SystemConfig.Instance.DeviceList);
            InitData();
        }

     

        private void InitData()
        {
            DeviceInfoModel = new ObservableCollection<DeviceInfoModel>();
            for (int i = 0; i < DeviceList.Count; i++)
            {
                DeviceInfoModel.Add(new DeviceInfoModel
                {
                    DeviceName = DeviceList[i].DeviceName,
                    Remark = DeviceList[i].Remark,
                    IsConnected = false,
                    IsEnabled= DeviceList[i].IsEnabled,
                    DeviceType= DeviceList[i].DeviceType,
                    CommunicationConfig= DeviceList[i].CommunicationConfig
                });
            }

            var progress = new Progress<(int index, bool isConnected)>();
            progress.ProgressChanged += (s, e) =>
            {
                DeviceInfoModel[e.index].IsConnected = e.isConnected;
            };

            var token = _devices.AppCancellationToken; 
            Task.Run(() => PollingConnection(progress, token));
        }

        private async Task PollingConnection(IProgress<(int index, bool isConnected)> progress, CancellationToken token)
        {
            while (!token.IsCancellationRequested)
            {
                for (int i = 0; i < DeviceList.Count; i++)
                {
                    bool isConnected = false;

                    if (_devices.DeviceDic.TryGetValue(DeviceList[i].Remark, out var device) && device != null)
                    {
                        switch (device)
                        {
                            case ITcp tcpDevice:
                                isConnected = tcpDevice.TcpClient?.Connected ?? false;
                                break;

                            case ISerialPort serialDevice:
                                isConnected = serialDevice.SerialPort?.IsOpen ?? false;
                                break;

                            case IModbusDevice modbusDevice:
                                isConnected = (modbusDevice.TcpClient?.Connected ?? false) || (modbusDevice.SerialPort?.IsOpen ?? false);
                                break;
                            default:
                                if (device is Backfeed backfeed)
                                {
                                    if (backfeed.CurrentDevice == "E36233A")
                                    {
                                        var e36233A = backfeed.CurrentInstance as E36233A;
                                        if (e36233A != null)
                                        {
                                            isConnected = e36233A.TcpClient?.Connected ?? false;
                                        }
                                    }
                                    else if (backfeed.CurrentDevice == "IT6724CReverse")
                                    {
                                        var it6724CReverse = backfeed.CurrentInstance as IT6724CReverse;
                                        if (it6724CReverse != null)
                                        {
                                            isConnected = it6724CReverse.SerialPort?.IsOpen ?? false;
                                        }
                                    }
                                }
                                break;
                        }
                        _eventAggregator.GetEvent<ConnectionChangeEvent>().Publish((DeviceList[i].Remark, isConnected));
                    }

                    progress.Report((i, isConnected));
                }

                await Task.Delay(200, token); // 支持取消
            }
        }



        #region 委托命令



        private void DeviceEdit()
        {
            if(SelectedDevice==null)
            {
                return;
            }
            var type = SelectedDevice.DeviceType.Split('.').Last();
            if(type=="E36233A"|| type == "IT6724CReverse")
            {
                _dialogService.Show("Backfeed");
            }
            else
            {
                _dialogService.Show(type);
            }
        }

        private void ParameterDelete()
        {
            Program.Parameters.Remove(SelectedParameter);
        }

        private void ParameterEdit()
        {
            var param = new DialogParameters
            {
                { "Mode",SelectedParameter==null?"ADD":"Edit" }
            };
            _dialogService.ShowDialog("ParameterSetting", param, (r) =>
            {
                if (r.Result == ButtonResult.OK)
                {
                    _eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
                }
                else
                {

                }
                
            });
        }

        private void ParameterAdd()
        {
            var param = new DialogParameters
            {
                { "Mode", "ADD" }
            };
            _dialogService.ShowDialog("ParameterSetting", param, (r) =>
            {
                if (r.Result == ButtonResult.OK)
                {
                    _eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
                }
                else
                {

                }
                
            });
        }
        private void Close()
        {
            if (SelectedDevice != null)
            {
                if (_devices.DeviceDic.TryGetValue(SelectedDevice.Remark, out var device) && device != null)
                {
                    Task.Run(() =>
                    {
                        switch (device)
                        {
                            case ITcp tcpDevice:
                                tcpDevice.Close();
                                break;

                            case ISerialPort serialDevice:
                                serialDevice.Close();
                                break;

                            case IModbusDevice modbusDevice:
                                modbusDevice.Close();
                                break;
                            default:
                                if (device is Backfeed backfeed)
                                {
                                    if (backfeed.CurrentDevice == "E36233A")
                                    {
                                        var e36233A = backfeed.CurrentInstance as E36233A;
                                        if (e36233A != null)
                                        {
                                            e36233A.Close();
                                        }
                                    }
                                    else if (backfeed.CurrentDevice == "IT6724CReverse")
                                    {
                                        var it6724CReverse = backfeed.CurrentInstance as IT6724CReverse;
                                        if (it6724CReverse != null)
                                        {
                                            it6724CReverse.Close();
                                        }
                                    }
                                }
                                break;

                        }
                    });
                }
            }
        }

        private void Reconnnect()
        {
            if (SelectedDevice != null)
            {
                if (_devices.DeviceDic.TryGetValue(SelectedDevice.Remark, out var device) && device != null)
                {
                    Task.Run(async () =>
                    {
                        try
                        {
                            switch (device)
                            {
                                case ITcp tcpDevice:
                                    await tcpDevice.ConnectAsync();
                                    
                                    break;

                                case ISerialPort serialDevice:
                                    await serialDevice.ConnectAsync();
                                    break;

                                case IModbusDevice modbusDevice:
                                    await modbusDevice.ConnectAsync();
                                    break;

                                default:
                                    if (device is Backfeed backfeed)
                                    {
                                        if (backfeed.CurrentDevice == "E36233A")
                                        {
                                            var e36233A = backfeed.CurrentInstance as E36233A;
                                            if (e36233A != null)
                                            {
                                                await e36233A.ConnectAsync();
                                            }
                                        }
                                        else if (backfeed.CurrentDevice == "IT6724CReverse")
                                        {
                                            var it6724CReverse = backfeed.CurrentInstance as IT6724CReverse;
                                            if (it6724CReverse != null)
                                            {
                                                await it6724CReverse.ConnectAsync();
                                            }
                                        }
                                    }
                                    break;
                            }
                        }
                        catch (Exception ex)
                        {
                            LoggerHelper.ErrorWithNotify($"设备重连时发生错误: {SelectedDevice.Remark} - {ex.Message}", ex.StackTrace);
                        }
                    });
                }
            }
        }

        #endregion

    }
}
