using Aitex.Core.RT.SCCore;
using System;
using System.Xml;
using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.IOCore;
using MECF.Framework.Common.Aitex.Core.Common.DeviceData;

namespace Aitex.Core.RT.Device.Devices
{
    public class IoSensorWaterFlowTemp : IoSensorAnalog
    {

        #region Variables

        private readonly DIAccessor _diFlowSW;
        private double _warnOffset;
        private readonly AITWaterFlowData _devData;
        
        #endregion

        #region Constructors

        public IoSensorWaterFlowTemp(string module, XmlElement node, string ioModule = "") 
            : base(module, node, ioModule)
        {
            _devData = new AITWaterFlowData();
            _diFlowSW = ParseDiNode("diFlowSW", node, ioModule);
            
            LoadConfig();
        }

        #endregion

        #region Properties

        /// <summary>
        /// 冷却水流侦测传感器信号。
        /// </summary>
        public bool IsFlowSw => _diFlowSW?.Value ?? false;

        private new AITWaterFlowData DeviceData
        {
            get
            {
                _devData.Update(base.DeviceData);
                _devData.IsFlowSW = IsFlowSw;
                return _devData;
            }
        }

        #endregion

        #region Methods

        protected sealed override void LoadConfig()
        {
            base.LoadConfig();

            var scNameWarnOffset = $"{ScBasePath}.WarningOffset";
            
            // 重新设定水温警告值，当前系统中的水温警告值非设定值，而是在Alarm基础上偏移指定的温度。
            _warnOffset = SC.SafeGetValue(scNameWarnOffset, 0.0);
            UpdateWarnThreshold(_warnOffset, _alarmLow, _alarmHigh);
            
            // 当WarnOffset、AlarmLow、AlarmHigh中的任意参数发生变更时，重新计算Warn阈值
            SC.RegisterValueChangedCallback(scNameWarnOffset, v =>
            {
                _warnOffset = (double)v;
                UpdateWarnThreshold(_warnOffset, _alarmLow, _alarmHigh);
            });

            if (!string.IsNullOrEmpty(_scNameAlarmLow))
            {
                SC.RegisterValueChangedCallback(_scNameAlarmLow,
                    v => UpdateWarnThreshold(_warnOffset, (double)v, _alarmHigh));
            }

            if (!string.IsNullOrEmpty(_scNameAlarmHigh))
            {
                SC.RegisterValueChangedCallback(_scNameAlarmHigh,
                    v => UpdateWarnThreshold(_warnOffset, _alarmLow, (double)v));
            }
        }

        public override bool Initialize()
        {
            DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
            DATA.Subscribe($"{Module}.CoolingWater.{Display}.Value", () => Value);
            DATA.Subscribe($"{Module}.CoolingWater.{Display}.FlowSensor", () => IsFlowSw);
            return base.Initialize();
        }

        /// <summary>
        /// 根据给定的Alarm阈值和偏移值计算Warn阈值。
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="alarmLow"></param>
        /// <param name="alarmHigh"></param>
        private void UpdateWarnThreshold(double offset, double alarmLow, double alarmHigh)
        {
            checked
            {
                _warningLow = alarmLow + Math.Abs(offset);
                _warningHigh = alarmHigh - Math.Abs(offset);
            }
        }
        
        #endregion
    }
}
