using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.IOCore;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using System;
using System.Collections.Concurrent;

namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.SMIFs.Fortrend
{
    public abstract class SMIFBase : BaseDevice, IDevice
    {
        protected bool IsInstalled;

        private string _scRoot;

        private bool _enableLog;

        //完成标志
        public bool IsDone = true;

        public bool IsHomeDone;

        public bool IsLoadDone;

        public bool IsUnloadDone;

        public bool IsLockDone;

        public bool IsUnLockDone;

        public bool IsSwitchDone;

        public bool IsCassetteExist => _diCassetteExist != null ? _diCassetteExist.Value : false;

        public string Mode;

        public string PortStatus;

        public bool IsPodPresent => _diPodInPlace != null ? _diPodInPlace.Value : false;

        public bool IsSMIFReady => _diReady != null ? _diReady.Value : false;

        public bool IsSMIFAlarm => _diAlarm != null ? _diAlarm.Value : true;

        public bool IsHomed;

        //当前错误码
        public int CurErrorCode;

        protected DIAccessor _diReady = null;

        protected DIAccessor _diAlarm = null;

        protected DIAccessor _diPodInPlace = null;

        protected DIAccessor _diReadyToUnload = null;

        protected DIAccessor _diCassetteExist = null;

        public DOAccessor DoUnloadEnable = null;

        public DOAccessor DoStartRun = null;

        public DOAccessor DoPortLock = null;

        public DOAccessor DoLoadEnable = null;

        public DOAccessor DoHomeEnable = null;

        private SerialPortEx _serialPort;

        public bool IsConnected => _serialPort != null ? _serialPort.IsOpen : false;

        private R_TRIG _trigger = new R_TRIG();

        public string Delimiter => _serialPort?.Delimiter;


        private readonly object _locker = new object();

        private ConcurrentQueue<string> _actionQueue = new ConcurrentQueue<string>();

        public SMIFBase()
        {

        }

        public SMIFBase(string module, string name)
        {
            Module = module;
            Name = name;
        }

        public virtual bool Initialize()
        {
            IsInstalled = SC.GetValue<bool>($"System.SetUp.Is{Module}Installed");

            if(IsInstalled )
            {
                InitSerialPort();
            }

            return true;
        }

        private void InitSerialPort()
        {
            try
            {
                string portName = string.Empty;
                if (string.IsNullOrEmpty(_scRoot))
                {
                    portName = SC.GetStringValue($"{Name}.PortName");
                    _enableLog = SC.GetValue<bool>($"{Name}.EnableLogMessage");
                }
                else
                {
                    portName = SC.GetStringValue($"{_scRoot}.{Module}.{Name}.PortName");
                    _enableLog = SC.GetValue<bool>($"{_scRoot}.{Module}.{Name}.EnableLogMessage");
                }

                _serialPort = new SerialPortEx(portName);
                _serialPort.Delimiter = "\r\n";
                _serialPort.OnReceivedEvent += OnReceived;

                _serialPort.Connect();
            }
            catch (Exception ex)
            {
                EV.PostAlarmLog(Module, $"{Module} connect IP:{_serialPort.PortName} failed");
                LOG.Error(ex.Message, ex);
            }
        }

        public virtual void OnReceived(string msg)
        {

        }

        protected void AddActionToQueue(string msg)
        {
            if (IsConnected)
                _actionQueue.Enqueue(msg);
        }

        protected void ClearCmdQueue()
        {
            lock (_locker)
            {
                //ConcurrentQueue<T>是线程安全的，所以它不会暴露或提供Clear方法清空
                while (_actionQueue.TryDequeue(out _))
                {

                }
            }
        }

        protected override void HandleMonitor()
        {
            if(!IsInstalled)
            {
                return;
            }

            //断连后将指令队列清空
            _trigger.CLK = !_serialPort.IsOpen;
            if (_trigger.Q)
            {
                ClearCmdQueue();
                EV.PostAlarmLog(Module, $"{_serialPort.PortName} Disconnected!");
            }

            lock (_locker)
            {
                //连接成功 && SMIF不是Alarm && SMIF 空闲状态
                if (_serialPort != null && _serialPort.IsOpen /*&& IsSMIFReady*/ && IsDone)
                {
                    if (_actionQueue.Count > 0 && _actionQueue.TryDequeue(out string msg))
                    {
                        IsDone = false;
                        SendMessage(msg);
                    }
                }
            }
        }

        private void SendMessage(string msg)
        {
            try
            {
                if (IsConnected)
                {
                    _serialPort.Send(msg);

                    if (!msg.StartsWith("FSR"))
                        EV.PostInfoLog(Module, $"向{Name}发送指令:{msg.Replace("\r", "").Replace("\n", "")}");
                }
            }
            catch (Exception ex)
            {
                LOG.Error(ex.Message);
            }
        }

        public virtual void Reset()
        {
            _serialPort?.Reset();
        }

        public virtual void Terminate()
        {
            _serialPort?.Close();
        }
    }
}
