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 StrongTemp : TempSensorBase
    {
        private StrongTempConnection _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 StrongTemp(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule)
        {
            RTrigs.Add(_trigCommunicationError);
            RTrigs.Add(_trigMonitorExcepted);
        }

        private void QueryTemp()
        {
            SetQuery("QueryADT", "*ADT00000a");
        }


        private void SetQuery(string name, string strCmd)
        {
            lock (_locker)
            {
                _lstHandler.Clear();
                if (_connection.IsBusy)
                {
                    _connection.ForceClear();
                }
                var bCmd = Encoding.Default.GetBytes(strCmd);

                _lstHandler.AddLast(new StrongTempQueryHandler(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 StrongTempConnection(Address);
            _connection.EnableLog(IsEnableLog);
            
            SC.RegisterValueChangedCallback($"TempSensors.EnableLogMessage", (obj) => { _connection.EnableLog((bool)obj); });
        }

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

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

                if (!_connection.IsConnected || _connection.IsCommunicationError)
                {

                    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);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _trigMonitorExcepted.CLK = true;
                if(_trigMonitorExcepted.Q)
                    LOG.Write(ex);
            }
        }
        
        public void ResponseQuery(string name, byte[] data)
        {
            try
            {
                if (name == "QueryADT")
                {

                    var sData = Encoding.Default.GetString(data);

                    if (sData.Length < 9)
                        return;

                    if (sData.Contains("*A"))
                    {
                        string sT = sData.Substring(2, 6);

                        _tempBuff[0] = Convert.ToSingle(sT);

                    }

                }

            }
            catch (Exception ex)
            {
                // ignored
            }
        }

        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 void Terminate()
        {
            _connection.Disconnect();
        }

    }
}
