using Aitex.Core.RT.IOCore;
using Aitex.Core.RT.SCCore;
using System.Xml;
using Aitex.Core.RT.Event;
using Aitex.Core.Util;

namespace Aitex.Core.RT.Device.Devices
{
    public class PSUPowerDetection : BaseDevice, IDevice
    {

        private readonly AIAccessor _aiPower;

        private readonly string _scMaxPower;

        /// <summary>
        /// 硬件最大物理功率
        /// </summary>
        private double _maxPower;

        private readonly string _scMaxHighPowerPercent;

        /// <summary>
        /// SC中配置的功率上限百分比
        /// </summary>
        private double _maxHighPowerPercent;

        private readonly R_TRIG _trigMaxPower = new();

        private readonly DeviceTimer _timer = new();


        public PSUPowerDetection(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule)
        {
            _aiPower = ParseAiNode("aiPower", node, ioModule);
            
            _scMaxPower = $"{ScBasePath}.{Name}.MaxPower";

            _scMaxHighPowerPercent = $"{ScBasePath}.{Name}.MaxHighPowerPercent";
            
        }

        protected override void HandleMonitor()
        {
            PowerOutput(_aiPower);
        }

        /// <summary>
        /// 连续2秒都超过最大功率
        /// </summary>
        /// <param name="power"></param>
        private void PowerOutput(AIAccessor power)
        {
            if (_maxHighPowerPercent == 0)
                return;

            var v = power.Value / _maxPower;
            // 计算百分比
            var percentage = v * 100.0;

            if (percentage > _maxHighPowerPercent)
            {
                if (_timer.IsIdle())
                    _timer.Start(2000);

                if (percentage <= _maxHighPowerPercent)//功率掉下来了，计时器停掉
                {
                    _timer.Stop();
                    return;
                }
                if (_timer.IsTimeout())
                {
                    PostWarning(power);
                }
            }
            else
            {
                _trigMaxPower.RST = true;
                _timer.Stop();
            }
        }

        private void PostWarning(AIAccessor power)
        {
            _trigMaxPower.CLK = true;
            if (_trigMaxPower.Q)
            {
                EV.PostWarningLog(Module, $"{Display} {power.Name} {power.Value} over maxPower {_maxPower}");
            }
        }

        public bool Initialize()
        {
            _maxPower = SC.SafeGetValue(_scMaxPower, double.PositiveInfinity);
            SC.RegisterValueChangedCallback(_scMaxPower, v => _maxPower = (double)v);

            _maxHighPowerPercent = SC.SafeGetValue(_scMaxHighPowerPercent, 100.0);
            SC.RegisterValueChangedCallback(_scMaxHighPowerPercent, v => _maxHighPowerPercent = (double)v);
            return true;
        }

        public void Terminate()
        {

        }

        public void Reset()
        {
            _trigMaxPower.RST = true;
            _timer.Stop();
        }
    }
}
