using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Communications;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Xml;

namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps
{
    public sealed class AETemp : TempSensorBase
    {
        private AETempConnection _connection;
        private readonly R_TRIG _trigCommunicationError = new ();
        private readonly R_TRIG _trigFewChannels = new ();
        private readonly R_TRIG _trigMonitorExcepted = new ();
        private readonly LinkedList<HandlerBase> _lstHandler = new ();
        private readonly object _locker = new ();
        private double[] _tempBuff;

        /// <summary>
        /// 设备通道启用
        /// </summary>
        private bool[] _channelInstalled;
        

        public override bool IsConnected => _connection is { IsConnected: true };
        

        public AETemp(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule)
        {
            RTrigs.Add(_trigCommunicationError);
            RTrigs.Add(_trigFewChannels);
            RTrigs.Add(_trigMonitorExcepted);
        }

        private void QueryTemp()
        {
            lock (_locker)
            {
                _lstHandler.AddLast(new AETempReadCommandHandler(this, "OUT", "1"));
            }
        }

        protected override bool HandleInitialize()
        {
            InitController();

            _channelInstalled=new bool[MaxChannels];

            for (int i = 0; i < _channelInstalled.Length; i++)
                _channelInstalled[i] = SC.GetValue<bool>($"{ScBasePath}.{Name}.Channel{i+1}");
            

            _tempBuff = new double[MaxChannels];
            return true;
        }

        private void InitController()
        {
            Address = SC.GetStringValue($"{ScBasePath}.{Name}.Address");
            _connection = new AETempConnection(Address);
            _connection.EnableLog(IsEnableLog);
            SC.RegisterValueChangedCallback($"TempSensors.EnableLogMessage", (obj) =>
            {
                _connection.EnableLog((bool)obj);
            });
        }

        protected override double[] HandleReadTemp()
        {
            OnTimeQueryTemp();
            return IsConnected ? _tempBuff : null;
        }

        protected void OnTimeQueryTemp()
        {
            try
            {
                _connection.MonitorTimeout();

                if (!_connection.IsConnected || _connection.IsCommunicationError)
                {
                    lock (_locker)
                    {
                        _lstHandler.Clear();
                    }

                    //只要断开，就进行连接
                    if (!_connection.Connect())
                    {
                        _trigCommunicationError.CLK = !_connection.IsConnected;
                        if (_trigCommunicationError.Q)
                        {
                            TempBasFunction.PM1PM2PostLog($"Can not connect with {_connection.Address}, {Module}.{Name}",EV.PostAlarmLog);

                            TempBasFunction.SetPm1Pm2IoForInterlock(true);
                        }
                        
                        _connection.ForceClear();
                        Thread.Sleep(1000);//重连延时
                    }
                    else
                    {
                        //连接成功后不会再进入，所以也只是写入一次LOG  
                        LOG.Write($"{Module} {Name} Connected");
                        EV.PostInfoLog(Module, $"{Name} Connected");
                        TempBasFunction.PM1PM2PostLog($"{Name} Connected", EV.PostInfoLog);
                        TempBasFunction.SetPm1Pm2IoForInterlock(false);
                    }
                    _trigCommunicationError.CLK = !_connection.IsConnected;
                    _connection.ForceClear();
                }
                else
                {
                    lock (_locker)
                    {
                        if (_lstHandler.Count == 0)
                            QueryTemp();
                        if (_lstHandler.Count > 0 && !_connection.IsBusy)
                        {
                            var handler = _lstHandler.First.Value;
                            _lstHandler.RemoveFirst();
                            if (handler != null)
                            {
                                _connection.Execute(handler);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _trigMonitorExcepted.CLK = true;
                if(_trigMonitorExcepted.Q)
                    LOG.Write(ex);
            }
        }
        
        public void ParseCommandInfo(string command, string message)
        {
            try
            {
                switch (command)
                {
                    case "OUT":
                        {
                            if (message != null)
                            {
                                if (message.Contains(" "))
                                {
                                    var strs = message.Split(' ');

                                    if (strs.Length > 0 ) 
                                    {
                                        //判断AE温度通道启用，和上位机设定通道启用，是否相同
                                        if (strs.Length != _channelInstalled.Count(c => c == true))
                                        {
                                            _trigFewChannels.CLK = true;
                                            if (_trigFewChannels.Q)
                                            {
                                                TempBasFunction.PM1PM2PostLog("AE Error: Too few channels.", EV.PostAlarmLog);
                                            }
                                            return;
                                        }

                                        //温度数组，根据通道是否屏蔽来赋值，
                                        _trigFewChannels.RST = true;
                                        for (int i = 0; i < strs.Length; i++)
                                        {
                                            if (_channelInstalled[i] == true)
                                            {
                                                _tempBuff[i] = float.Parse(strs[i]);
                                            }
                                        }

                                        //温度连续多次不变化侦测
                                        //TempInvariantCount = TempBasFunction.TempInvariantCount(TempDatasArray, out string tempInvariantData);
                                        //_trigTempNoChange.CLK = TempInvariantCount >= TempInvariantCountMax ? true : false;
                                        //if (_trigTempNoChange.Q)
                                        //{
                                        //    TempBasFunction.PM1PM2PostLog($"{Name} {TempInvariantCount} temp no changeCount {tempInvariantData}", EV.PostWarningLog);
                                        //}
                                    }
                                }
                            }
                        }
                        break;
                }
            }
            catch (Exception ex)
            {
                // ignored
            }
        }


        public override void Reset()
        {
            _connection?.SetCommunicationError(false, "");
            base.Reset();
        }

        public override void Terminate()
        {
            _connection.Disconnect();
        }

    }
}
