using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.Util;
using MECF.Framework.Common.Communications;
using System;
using Aitex.Core.RT.SCCore;

namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.MachineVision.HikVision
{
    public class HikMV : BaseDevice, IDevice, IConnection
    {
        private readonly HikMVConnection _connection;
        private readonly object _locker = new();
        private int _retryCount = 0;
        private PeriodicJob _thread;
        private const int _maxRetryCount = 50;
        private readonly R_TRIG _trigConnErr = new();

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

        public string Address => _connection.Address;

        public bool IsResponded { get; set; }

        public bool IsProcessing { get; set; } = false;

        public string RawMessage { get; set; } = "";

        public double[] Data { get; set; }


        public HikMV(string module, string scRoot, string name) : base(module, name, name, name)
        {

            var ip = SC.SafeGetStringValue($"{name}.IP", "127.0.0.1");
            var port = SC.GetValue($"{name}.Port", 9000);
            
            _connection = new HikMVConnection($"{ip}:{port}","\r\n");

        }

        public bool Initialize()
        {
            DATA.Subscribe($"{UniqueName}.{nameof(RawMessage)}", () => RawMessage);
            OP.Subscribe($"{UniqueName}.Execute", (string cmd, object[] args) => Execute((string)args[0]));

            if (!_connection.Connect())
            {
                _trigConnErr.CLK = true;
                if(_trigConnErr.Q)
                    EV.PostAlarmLog(Module, $"{Name}({Address}) Connect Failed");
            }
            _thread = new PeriodicJob(100, OnTimer, $"{UniqueName} MonitorHandler", true);
            return true;
        }

        private bool OnTimer()
        {
            var result = _connection.MonitorTimeout();
            if (result != null)
            {
                RawMessage = $"{result.SendText.Replace("\r", "").Replace("\n", "")} no Response";
                IsProcessing = false;
                Disconnect();
            }
            if (!_connection.IsConnected)
            {
                if (_retryCount < _maxRetryCount)
                {
                    _retryCount++;
                }
                else
                {
                    _retryCount = 0;
                    lock (_locker)
                    {
                        if (!_connection.Connect())
                        {
                            // 连接失败
                            _trigConnErr.CLK = true;
                            if(_trigConnErr.Q)
                                EV.PostAlarmLog(Module, $"{Name}({Address}) Connect Failed");   
                        }
                        else
                        {
                            // 连接成功
                            _trigConnErr.CLK = false;
                        }
                    }
                }
            }
            return true;
        }

        public bool Execute(string command)
        {
            IsResponded = false;
            IsProcessing = true;
            RawMessage = "";
            var handler = new HikMVHandler(this, command+"\r\n");
            handler.AckTimeout = TimeSpan.FromSeconds(5.0);
            _connection.Execute(handler);
            return true;
        }

        public void Reset()
        {
            _trigConnErr.RST = true;
            IsProcessing = false;
            IsResponded = false;
            RawMessage = "";
        }

        public void Terminate()
        {
            Disconnect();
            _trigConnErr.RST = true;
        }

        public bool Connect()
        {
            return _connection.Connect();
        }

        public bool Disconnect()
        {
            return _connection.Disconnect();
        }
    }
}
