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.Text;
using System.Threading;
using System.Xml;

namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps
{
    public class SensorTemp : TempSensorBase
    {
        private SensorTempConnection _connection;
        private readonly R_TRIG _trigCommunicationError = new ();
        private readonly R_TRIG _trigMonitorExcepted = new ();
        private readonly LinkedList<HandlerBase> _lstHandler = new();
        private readonly object _locker = new ();
        private string PMName;
        private double[] _tempBuff;
        
        public override bool IsConnected => _connection is { IsConnected: true };

       

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

        private void QueryTemp()
        {
            SetQuery("QueryBup", "00mw0\r");
        }

        private void SetQuery(string name, string strCmd)
        {
            lock (_locker)
            {
                if (_connection.IsBusy)
                {
                    _connection.ForceClear();
                }

                byte[] bCmd = Encoding.Default.GetBytes(strCmd);

                _lstHandler.AddLast(new SensorTempQueryHandler(this, name, bCmd));

            }
        }


        protected override bool HandleInitialize()
        {
            InitController();
            _tempBuff = new double[MaxChannels];
            return true;
        }

        private void InitController()
        {
            //添加参数设置
            PMName = SC.GetStringValue($"{ScBasePath}.{Name}.PMName");
            Address = SC.GetStringValue($"{ScBasePath}.{Name}.Address");
            _connection = new SensorTempConnection(Address);
            _connection.EnableLog(IsEnableLog);
            
            SC.RegisterValueChangedCallback($"TempSensors.EnableLogMessage", (obj) =>
            {
                _connection.EnableLog((bool)obj);
            });
        }

        protected override void HandleMonitor()
        {
            try
            {
                _connection.MonitorTimeout();

                if (!_connection.IsConnected)
                {

                    lock (_locker)
                    {
                        _lstHandler.Clear();
                    }

                    //只要断开，就进行连接
                    if (!_connection.Connect())
                    {
                        _trigCommunicationError.CLK = !_connection.IsConnected;
                        if (_trigCommunicationError.Q)
                        {
                            Thread.Sleep(2000);//不加延时软件刚启动可能不打印
                            TempBasFunction.PMPostLog(PMName, $"Can not connect with {_connection.Address}, {Name}", EV.PostAlarmLog);
                            TempBasFunction.SetPmIoForInterlock(PMName, true);
                        }
                    }
                    else//已连接，自动复位断联信号
                    {
                        _trigCommunicationError.RST = true;
                        TempBasFunction.PMPostLog(PMName, $"{PMName} {Name} {Address} reconnected.", EV.PostInfoLog);
                        TempBasFunction.SetPmIoForInterlock(PMName, false);
                    }
                    Thread.Sleep(1000);//重连延时
                    _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);

                        }
                    }
                }

                if (_connection.IsCommunicationError)
                {
                    //ResponseError();
                }
                
                _trigMonitorExcepted.CLK = false;
            }
            catch (Exception ex)
            {
                _trigMonitorExcepted.CLK = true;
                if(_trigMonitorExcepted.Q)
                    LOG.Write(ex);
            }
        }

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

        public void ResponseQuery(string name, byte[] data)
        {
            try
            {
                var sData = Encoding.Default.GetString(data);
                if (name == "QueryBup")
                {
                    if (!sData.Contains("\r"))
                        return;

                    var strTemp = sData.Replace("\r", "");

                    var temp = (float)Convert.ToInt32(strTemp, 16) / 10;

                    if (temp < MinimalTemp - 10 || temp > 2000)//过滤因通讯数据截取，导致的异常
                    {
                        LOG.Write($"{Module} {Name} temp error :{temp}");
                        return;
                    }

                    _tempBuff[0] = temp ;


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

            }
            catch (Exception ex)
            {

            }
        }

        public void ResponseError()
        {
            _trigCommunicationError.CLK = true;
            if (_trigCommunicationError.Q)
            {
                TempBasFunction.PMPostLog(PMName, $"{PMName} {Name} {Address} could not receive temp", EV.PostAlarmLog);
                TempBasFunction.SetPmIoForInterlock(PMName, true);
            }
            
        }
        
        public override bool Connect()
        {
            return _connection.Connect();
        }

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

    }
}
