using DH.Commons.Enums;
using OpenCvSharp.Internal;
using System;
using System.ComponentModel;
using System.IO;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using static DH.Commons.Enums.EnumHelper;
using Timer = System.Threading.Timer;

namespace DH.Commons.Base
{
    public abstract class DeviceBase : IDisposable
    {
        #region Event
        [JsonIgnore]
        [Browsable(false)]
        public Action<DateTime, Exception> OnExceptionOccured { get; set; }
        //public event Action<DateTime, LogLevel, string> OnLog;
        public event Action<LogMsg> OnLog;
      //  public event Action<IDevice, DeviceState> OnDeviceStateChanged;
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        #region field
        int RetryTime = 3;
        /// <summary>
        /// 和设备暂停状态关联的信号量
        /// </summary>
        private readonly ManualResetEvent pauseHandle = new ManualResetEvent(true);
        readonly Timer stateChangedTimer;
        #endregion

        #region Property
        #region State
        private EnumHelper.DeviceState _currentStateToBe = EnumHelper.DeviceState.DSUninit;
        /// <summary>
        /// 当前设备状态
        /// </summary>
        [JsonIgnore]
        internal EnumHelper.DeviceState CurrentStateToBe
        {
            get
            {
                return _currentStateToBe;
            }
            set
            {
                if (value != _currentStateToBe)
                {
                    var initialState = _currentStateToBe;
                    _currentStateToBe = value;

                    if (_currentStateToBe != EnumHelper.DeviceState.DSExcept)
                    {
                      //  OnStateChanged(initialState);
                    }
                    else
                    {
                        stateChangedTimer.Change(Timeout.Infinite, Timeout.Infinite);
                    }
                }
            }
        }

        //private EnumHelper.DeviceState initialState = EnumHelper.DeviceState.DSUninit;
        private EnumHelper.DeviceState _currentState = EnumHelper.DeviceState.DSUninit;
        public EnumHelper.DeviceState CurrentState
        {
            get
            {
                return _currentState;
            }
            set
            {
                _currentState = value;

                if (value != EnumHelper.DeviceState.TBD)
                {
                  //  OnDeviceStateChanged?.Invoke(this, _currentState);
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentState"));
                }
                //else
                //{
                //    initialState = _currentState;
                //}
            }
        }
        #endregion

        /// <summary>
        /// 设备标识符 从数据库获取
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// 设备名称 从数据库获取
        /// </summary>
        public string Name { get; set; }

        //private IInitialConfig initialConfig = null;
        ///// <summary>
        ///// 设备初始化配置 从数据库获取
        ///// </summary>
        //public virtual IInitialConfig InitialConfig
        //{
        //    get => initialConfig;
        //    set
        //    {
        //        initialConfig = value;
        //        Id = initialConfig.Id;
        //        Name = initialConfig.Name;

        //        LoggerHelper.LogPath = initialConfig.LogPath;
        //        LoggerHelper.LogPrefix = initialConfig.Name;
        //    }
        //}
        #endregion

        #region 构造函数
        public DeviceBase()
        {
            RegisterFileWriterException();
           // stateChangedTimer = new Timer(new TimerCallback(CheckDeviceOpTimeOut), null, Timeout.Infinite, Timeout.Infinite);
        }
        #endregion

        #region 设备抽象方法
        protected virtual void Init()
        {
            LogAsync(DateTime.Now, LogLevel.Information, $"{Name}初始化完成");
        }

       

        protected virtual void Start()
        {
            LogAsync(DateTime.Now, LogLevel.Information, $"{Name}启动");
        }

        protected virtual void Stop()
        {
            LogAsync(DateTime.Now, LogLevel.Information, $"{Name}停止");
        }

        //public abstract void AttachToProcess(IProcess process);
        #endregion

        /// <summary>
        /// 常用操作封装方法
        /// </summary>
        /// <param name="opConfig"></param>
        /// <returns></returns>
        //public virtual ResponseMessage RunWrap(IOperationConfig opConfig)
        //{
        //    ResponseMessage msg = new ResponseMessage();
        //    msg.Message = "设备基类默认操作";
        //    return msg;
        //}

        #region 状态切换            
        //[DeviceExceptionAspect]
        //public void StateChange(EnumHelper.DeviceState stateToBe)
        //{
        //    if (CurrentState == stateToBe)
        //    {
        //        return;
        //    }

        //    if (!stateToBe.CheckPreStateValid((int)CurrentStateToBe))
        //    {
        //        string currentStateStr = CurrentStateToBe.GetEnumDescription();
        //        string stateToBeStr = stateToBe.GetEnumDescription();
        //        throw new ProcessException($"{InitialConfig.Name}设备的当前状态为{currentStateStr},无法切换至{stateToBeStr}");
        //    }

        //    CurrentState = EnumHelper.DeviceState.TBD;
        //    CurrentStateToBe = stateToBe;
        //}

        //[DeviceExceptionAspect]
        //private void OnStateChanged(EnumHelper.DeviceState initialState)
        //{
        //    try
        //    {
        //        if (CurrentStateToBe != EnumHelper.DeviceState.DSExcept)
        //        {
        //        }
        //        else
        //        {
        //            if (CurrentState == EnumHelper.DeviceState.DSExcept)
        //            {
        //                return;
        //            }
        //            else
        //            {
        //                throw new ProcessException($"{InitialConfig.Name}设备操作超时");
        //            }
        //        }

        //        if (RetryTime >= 0)
        //        {
        //            if (initialState == CurrentStateToBe)
        //            {
        //                CurrentState = CurrentStateToBe;
        //                return;
        //            }

        //            #region 状态切换操作
        //            switch (CurrentStateToBe)
        //            {
        //                case EnumHelper.DeviceState.DSInit:
        //                    if (initialState == EnumHelper.DeviceState.DSOpen)
        //                    {
        //                        return;
        //                    }
        //                    else
        //                    {
        //                        Init();
        //                    }
        //                    break;
        //                case EnumHelper.DeviceState.DSOpen:
        //                    if (initialState == EnumHelper.DeviceState.DSInit)
        //                    {
        //                        Start();
        //                    }
        //                    else if (initialState == EnumHelper.DeviceState.DSPause)
        //                    {
        //                        Resume();
        //                        pauseHandle.Set();
        //                    }
        //                    break;
        //                case EnumHelper.DeviceState.DSPause:
        //                    pauseHandle.Reset();
        //                    Pause();
        //                    break;
        //                case EnumHelper.DeviceState.DSClose:
        //                    if (initialState != DeviceState.DSUninit)
        //                    {
        //                        Stop();
        //                    }
        //                    break;
        //                default:
        //                    break;
        //            }

        //            RetryTime = 3;
        //            CurrentState = CurrentStateToBe;
        //            #endregion
        //        }

        //        stateChangedTimer.Change(Timeout.Infinite, Timeout.Infinite);
        //    }
        //    catch (Exception ex)
        //    {
        //        RetryTime--;
        //        if (RetryTime > 0)
        //        {
        //            OnStateChanged(initialState);
        //        }
        //        else
        //        {
        //            if (CurrentState != EnumHelper.DeviceState.DSExcept)
        //            {
        //                RetryTime = 3;
        //                throw new ProcessException($"设备{InitialConfig.Name}的{CurrentStateToBe.GetEnumDescription()}操作重复3次失败", ex, ExceptionLevel.Warning);
        //            }
        //        }
        //    }
        //}

        //private void CheckDeviceOpTimeOut(object state)
        //{
        //    stateChangedTimer?.Change(Timeout.Infinite, Timeout.Infinite);

        //    if (CurrentState != EnumHelper.DeviceState.DSExcept)
        //    {
        //        StateChange(EnumHelper.DeviceState.DSExcept);
        //    }
        //}
        #endregion

        #region 日志处理
        private void RegisterFileWriterException()
        {
            LoggerHelper.OnLogExceptionRaised -= LoggerHelper_OnLogExceptionRaised;
           // CSVHelper.OnCSVExceptionRaised -= LoggerHelper_OnLogExceptionRaised;

            LoggerHelper.OnLogExceptionRaised += LoggerHelper_OnLogExceptionRaised;
           // CSVHelper.OnCSVExceptionRaised += LoggerHelper_OnLogExceptionRaised;
        }
      //  public CSVHelper CSVHelper { get; set; } = new CSVHelper();

        public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper();

        public virtual void LogAsync(LogMsg msg)
        {
            msg.MsgSource = Name;
            msg.ThreadId = Thread.CurrentThread.ManagedThreadId;

            //OnLog?.BeginInvoke(msg, null, null);
            OnLog?.Invoke(msg);

            //if (InitialConfig.IsEnableLog)
            //{
                LoggerHelper.LogAsync(msg);
            //}
        }

        public virtual void LogAsync(DateTime dt, LogLevel logLevel, string msg)
        {
            LogAsync(new LogMsg(dt, logLevel, msg));
        }
        private void LoggerHelper_OnLogExceptionRaised(DateTime dt, string msg)
        {
            OnLog?.Invoke(new LogMsg(dt, LogLevel.Error, msg));
        }
        /// <summary>
        /// CSV异步数据输出
        /// </summary>
        /// <param name="csvFile">CSV输出文件的文件全路径</param>
        /// <param name="csvData">CSV输出数据</param>
        /// <param name="csvHead">CSV文件表头</param>
        public virtual void CSVRecordAsync(string csvFile, string csvData, string csvHead = "")
        {
         //   CSVHelper.CSVOutputAsync(csvFile, csvData, csvHead);
        }
        #endregion

        #region 报警记录
        //object _alarmLock = new object();
        //protected virtual async void SaveAlarmCSVAsync(DateTime now, string deviceName, IWarningSet ws)
        //{
        //    await Task.Run(() =>
        //    {
        //        LogAsync(now, LogLevel.Warning, $"{ws.WarningCode}-{ws.WarningDescription} {(ws.CurrentStatus ? "发生" : "取消")}");

        //        if (string.IsNullOrWhiteSpace(this.InitialConfig.LogPath) || !InitialConfig.IsEnableCSV)
        //            return;

        //        string path = Path.Combine(InitialConfig.LogPath, $"Alarm_{Name}_{now.ToString("yyyyMMdd")}.csv");
        //        string head = "Time,Source,AlarmCode,AlarmDescription,AlarmStatus";
        //        string data = $"{now.ToString("HH:mm:ss.fff")},{deviceName},{ws.WarningCode},{ws.WarningDescription},{(ws.CurrentStatus ? "报警发生" : "报警取消")}";
        //        CSVRecordAsync(path, data, head);
        //    });
        //}
        #endregion

        #region IDisposable Support        
        private bool disposedValue = false; // 要检测冗余调用

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    //释放托管状态(托管对象)。
                    stateChangedTimer?.Dispose();
                    pauseHandle?.Dispose();
                }

                // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
                // TODO: 将大型字段设置为 null。

                disposedValue = true;
            }
        }

        // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
        // ~DeviceBase()
        // {
        //   // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
        //   Dispose(false);
        // }

        // 添加此代码以正确实现可处置模式。
        public void Dispose()
        {
            // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
            Dispose(true);
            // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
            // GC.SuppressFinalize(this);
        }
        #endregion
    }
}