using Stylet;
using System;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace MainShell.DeviceMaintance.ViewModel.State
{
    public class DeviceIoPageState : PropertyChangedBase
    {
        private DateTime _lastRefreshTime = DateTime.MinValue;
        private DateTime _lastWriteTime = DateTime.MinValue;
        private bool _isOnline;
        private bool _isWriteSuccess;
        private string _lastWriteMessage = "等待写入操作";

        public DateTime LastRefreshTime
        {
            get { return _lastRefreshTime; }
            set { SetAndNotify(ref _lastRefreshTime, value); }
        }

        public DateTime LastWriteTime
        {
            get { return _lastWriteTime; }
            set { SetAndNotify(ref _lastWriteTime, value); }
        }

        public bool IsOnline
        {
            get { return _isOnline; }
            set
            {
                if (SetAndNotify(ref _isOnline, value))
                {
                    OnPropertyChanged(nameof(OnlineText));
                }
            }
        }

        public bool IsWriteSuccess
        {
            get { return _isWriteSuccess; }
            set { SetAndNotify(ref _isWriteSuccess, value); }
        }

        public string LastWriteMessage
        {
            get { return _lastWriteMessage; }
            set { SetAndNotify(ref _lastWriteMessage, value); }
        }

        public string OnlineText
        {
            get { return IsOnline ? "在线" : "离线/模拟"; }
        }

        public ObservableCollection<DeviceIoModuleState> Modules { get; } = new ObservableCollection<DeviceIoModuleState>();
    }

    public class DeviceIoModuleState : PropertyChangedBase
    {
        private string _name;

        public string Name
        {
            get { return _name; }
            set { SetAndNotify(ref _name, value); }
        }

        public ObservableCollection<DeviceIoPointItemState> InputPoints { get; } = new ObservableCollection<DeviceIoPointItemState>();
        public ObservableCollection<DeviceIoPointItemState> OutputPoints { get; } = new ObservableCollection<DeviceIoPointItemState>();

        public bool HasInputs
        {
            get { return InputPoints.Count > 0; }
        }

        public bool HasOutputs
        {
            get { return OutputPoints.Count > 0; }
        }
    }

    public class DeviceIoPointItemState : PropertyChangedBase
    {
        private bool _isOn;
        private bool _canWrite;

        public int Id { get; set; }
        public string PointKey { get; set; }
        public string Module { get; set; }
        public string Name { get; set; }
        public int StationNo { get; set; }
        public string LineNo { get; set; }
        public string Description { get; set; }
        public bool IsOutput { get; set; }
        public bool IsInverse { get; set; }

        public bool IsOn
        {
            get { return _isOn; }
            set
            {
                if (SetAndNotify(ref _isOn, value))
                {
                    OnPropertyChanged(nameof(StateText));
                    OnPropertyChanged(nameof(ToggleText));
                }
            }
        }

        public bool CanWrite
        {
            get { return _canWrite; }
            set { SetAndNotify(ref _canWrite, value); }
        }

        public string StateText
        {
            get { return IsOn ? "ON" : "OFF"; }
        }

        public string ToggleText
        {
            get { return IsOn ? "ON" : "OFF"; }
        }

        public ICommand ToggleCommand { get; set; }
    }

    public class ActionCommand : ICommand
    {
        private readonly Action _execute;
        private readonly Func<bool> _canExecute;

        public ActionCommand(Action execute, Func<bool> canExecute = null)
        {
            _execute = execute;
            _canExecute = canExecute;
        }

        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute();
        }

        public void Execute(object parameter)
        {
            _execute();
        }

        public void RaiseCanExecuteChanged()
        {
            var handler = CanExecuteChanged;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    }
}
