using System;
using System.Xml;
using Aitex.Core.Common.DeviceData;
using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using Aitex.Core.RT.Tolerance;
using Aitex.Core.Util;

namespace MECF.Framework.Common.Device.Bases
{
	public abstract class MfcBase : BaseDevice, IDevice
	{
		private DeviceTimer rampTimer = new DeviceTimer();

		protected float rampTarget;

		private float rampInitValue;

		private int rampTime;

		private float _currentWarningRange;

		private float _currentAlarmRange;

		protected ToleranceChecker _toleranceAlarmChecker = new ToleranceChecker();

		protected ToleranceChecker _toleranceWarningChecker = new ToleranceChecker();

		protected SCConfigItem _scGasName;

		protected SCConfigItem _scEnable;

		protected SCConfigItem _scN2Scale;

		protected SCConfigItem _scN2MinimumFlow;

		protected SCConfigItem _scScaleFactor;

		protected SCConfigItem _scAlarmRange;

		protected SCConfigItem _scEnableAlarm;

		protected SCConfigItem _scAlarmTime;

		protected SCConfigItem _scWarningTime;

		protected SCConfigItem _scWarningRange;

		protected SCConfigItem _scDefaultSetPoint;

		protected SCConfigItem _scRegulationFactor;

		private SCConfigItem _scFineTuningEnable;

		private SCConfigItem _scFineTuningValue;

		private R_TRIG _trigOffline = new R_TRIG();

		protected double _currentFineTuningValue;

		protected string _uniqueName;

		/// <summary>
		/// 返回MFC量程。
		/// </summary>
		public virtual float Scale
		{
			get
			{
				if (_scN2Scale == null || _scScaleFactor == null)
				{
					return 100f;
				}
				return (float)(_scN2Scale.DoubleValue * _scScaleFactor.DoubleValue);
			}
		}

		public virtual float MinimumFlow { get; set; }

		/// <summary>
		/// 设置或返回MFC流程设定值。
		/// </summary>
		public virtual float SetPoint { get; set; }

		/// <summary>
		/// 设置或返回MFC当前流量的反馈值。
		/// </summary>
		public virtual float FeedBack { get; set; }

		/// <summary>
		/// 返回MFC流量是否超过阈值。
		/// </summary>
		public bool IsOutOfTolerance => _toleranceAlarmChecker.Result;

		/// <summary>
		/// 返回当MFC流量超过限制时是否产生Alarm。
		/// </summary>
		public virtual bool EnableAlarm
		{
			get
			{
				if (_scEnableAlarm != null)
				{
					return _scEnableAlarm.BoolValue;
				}
				return false;
			}
		}

		public virtual double AlarmTime
		{
			get
			{
				if (_scAlarmTime != null)
				{
					return (_scAlarmTime.IntValue != 0) ? ((double)_scAlarmTime.IntValue) : _scAlarmTime.DoubleValue;
				}
				return 10.0;
			}
		}

		public virtual double AlarmRange
		{
			get
			{
				if (_currentAlarmRange > 0f)
				{
					return _currentAlarmRange;
				}
				if (_scAlarmRange != null)
				{
					return _scAlarmRange.DoubleValue;
				}
				return 0.0;
			}
		}

		public virtual double WarningTime
		{
			get
			{
				if (_scWarningTime != null)
				{
					return _scWarningTime.DoubleValue;
				}
				return 0.0;
			}
		}

		public virtual double WarningRange
		{
			get
			{
				if (_currentWarningRange > 0f)
				{
					return _currentWarningRange;
				}
				if (_scWarningRange != null)
				{
					return _scWarningRange.DoubleValue;
				}
				return 0.0;
			}
		}

		public virtual double FineTuningValue
		{
			get
			{
				if (_scFineTuningEnable == null || !_scFineTuningEnable.BoolValue)
				{
					return 1.0;
				}
				if (_currentFineTuningValue != 0.0)
				{
					return 1.0 + _currentFineTuningValue / 100.0;
				}
				return (_scFineTuningValue != null) ? (1.0 + _scFineTuningValue.DoubleValue / 100.0) : 1.0;
			}
		}

		public string DisplayName
		{
			get
			{
				if (_scGasName != null)
				{
					return _scGasName.StringValue;
				}
				return base.Display;
			}
		}

		public virtual AITMfcData DeviceData => new AITMfcData
		{
			UniqueName = _uniqueName,
			Type = "MFC",
			DeviceName = base.Name,
			DeviceSchematicId = base.DeviceID,
			DisplayName = DisplayName,
			FeedBack = ((SetPoint == 0f) ? 0f : FeedBack),
			SetPoint = SetPoint,
			Scale = Scale
		};

		public MfcBase()
		{
		}

		public MfcBase(string module, XmlElement node, string ioModule = "")
		{
			Unit = node.GetAttribute("unit");
			base.Module = (string.IsNullOrEmpty(node.GetAttribute("module")) ? module : node.GetAttribute("module"));
			base.Name = node.GetAttribute("id");
			base.Display = node.GetAttribute("display");
			base.DeviceID = node.GetAttribute("schematicId");
			_scGasName = ParseScNode("scGasName", node, ioModule, base.Module + "." + base.Name + ".GasName");
			_scEnable = ParseScNode("scEnable", node);
			_scN2Scale = ParseScNode("scN2Scale", node, ioModule, base.Module + "." + base.Name + ".N2Scale");
			_scScaleFactor = ParseScNode("scScaleFactor", node, ioModule, base.Module + "." + base.Name + ".ScaleFactor");
			_scAlarmRange = ParseScNode("scAlarmRange", node, ioModule, base.Module + "." + base.Name + ".AlarmRange");
			_scEnableAlarm = ParseScNode("scEnableAlarm", node, ioModule, base.Module + "." + base.Name + ".EnableAlarm");
			_scAlarmTime = ParseScNode("scAlarmTime", node, ioModule, base.Module + "." + base.Name + ".AlarmTime");
			_scWarningTime = ParseScNode("scWarningTime", node, ioModule, base.Module + "." + base.DeviceID + ".WarningTime");
			_scWarningRange = ParseScNode("scWarningRange", node, ioModule, base.Module + "." + base.DeviceID + ".WarningRange");
			_scFineTuningValue = ParseScNode("scFineTuningValue", node, ioModule, base.Module + ".FineTuning." + base.Name);
			_scFineTuningEnable = ParseScNode("scFineTuningEnable", node, ioModule, base.Module + ".FineTuning.IsEnable");
			_scDefaultSetPoint = ParseScNode("scDefaultSetPoint", node);
			_scRegulationFactor = ParseScNode("scFlowRegulationFactor", node, ioModule, base.Module + "." + base.Name + ".RegulationFactor");
			_uniqueName = base.Module + "." + base.Name;
		}

		public virtual bool Initialize()
		{
			DATA.Subscribe(base.Module + "." + base.Name + ".DeviceData", () => DeviceData);
			DATA.Subscribe(base.Module + "." + base.Name + ".FlowFeedback", () => FeedBack);
			DATA.Subscribe(base.Module + "." + base.Name + ".FlowSetPoint", () => SetPoint);
			OP.Subscribe(base.Module + "." + base.Name + ".SetMfcFlow", delegate(string function, object[] args)
			{
				SetMfcFlow(Convert.ToSingle(args[0]));
				return true;
			});
			OP.Subscribe(base.Module + "." + base.Name + ".Ramp", delegate(string function, object[] args)
			{
				SetMfcFlow(Convert.ToSingle(args[0]));
				return true;
			});
			OP.Subscribe(base.Module + "." + base.Name + ".SetFineTuning", delegate(out string reason, int time, object[] param)
			{
				reason = string.Empty;
				SetFineTuning(Convert.ToSingle(param[0]));
				return true;
			});
			OP.Subscribe(base.Module + "." + base.Name + ".SetTolerance", delegate(out string reason, int time, object[] param)
			{
				reason = string.Empty;
				float num = Convert.ToSingle(param[0]);
				float num2 = Convert.ToSingle(param[1]);
				SetTolerance(num, num2);
				return true;
			});
			InitSc();
			return true;
		}

		public virtual void InitSc()
		{
			_scGasName = SC.GetConfigItem(base.ScBasePath + "." + base.Name + ".GasName");
			_scEnable = SC.GetConfigItem(base.ScBasePath + "." + base.Name + ".Enable");
			_scN2Scale = SC.GetConfigItem(base.ScBasePath + "." + base.Name + ".N2Scale");
			_scScaleFactor = SC.GetConfigItem(base.ScBasePath + "." + base.Name + ".ScaleFactor");
			_scEnableAlarm = SC.GetConfigItem(base.ScBasePath + "." + base.Name + ".EnableAlarm");
			_scAlarmRange = SC.GetConfigItem(base.ScBasePath + "." + base.Name + ".AlarmRange");
			_scAlarmTime = SC.GetConfigItem(base.ScBasePath + "." + base.Name + ".AlarmTime");
			_scWarningRange = SC.GetConfigItem(base.ScBasePath + "." + base.Name + ".WarningRange");
			_scWarningTime = SC.GetConfigItem(base.ScBasePath + "." + base.Name + ".WarningTime");
		}

		public virtual void SetTolerance(float warning, float alarm)
		{
			_currentWarningRange = warning;
			_currentAlarmRange = alarm;
			_toleranceAlarmChecker.Reset(AlarmTime);
			_toleranceWarningChecker.Reset(WarningTime);
		}

		public virtual void CheckTolerance()
		{
			if (EnableAlarm && SetPoint != 0f)
			{
				_toleranceAlarmChecker.Monitor(FeedBack, (double)SetPoint * (1.0 - AlarmRange / 100.0), (double)SetPoint * (1.0 + AlarmRange / 100.0), AlarmTime);
				_toleranceWarningChecker.Monitor(FeedBack, (double)SetPoint * (1.0 - WarningRange / 100.0), (double)SetPoint * (1.0 + WarningRange / 100.0), WarningTime);
			}
		}

		public virtual bool CheckToleranceAlarm()
		{
			if (!EnableAlarm)
			{
				return false;
			}
			return _toleranceAlarmChecker.Result;
		}

		public virtual bool CheckToleranceWarning()
		{
			if (!EnableAlarm)
			{
				return false;
			}
			return _toleranceWarningChecker.Result;
		}

		public virtual void SetFineTuning(float fineTuning)
		{
			_currentFineTuningValue = fineTuning;
		}

		public virtual void SetMfcFlow(float flow)
		{
		}

		public virtual bool SetMfcFlow(int time, float flow, out string reason)
		{
			reason = "";
			return true;
		}

		private bool InvokeRamp(string method, object[] args)
		{
			float val = Convert.ToSingle(args[0].ToString());
			val = Math.Min(val, Scale);
			val = Math.Max(val, 0f);
			int num = 0;
			if (args.Length >= 2)
			{
				num = Convert.ToInt32(args[1].ToString());
			}
			Ramp(val, num);
			EV.PostInfoLog(base.Module, $"{_uniqueName} ramp to {val}{Unit} in {num} seconds");
			return true;
		}

		public virtual void Monitor()
		{
			MonitorRamping();
			MonitorTolerance();
		}

		public virtual void Reset()
		{
			_toleranceAlarmChecker.Reset(AlarmTime);
			_toleranceWarningChecker.Reset(WarningTime);
			_trigOffline.RST = true;
		}

		public virtual void Terminate()
		{
			Ramp(0f, 0);
		}

		public void Ramp(int time)
		{
			Ramp(0f, time);
		}

		public void Ramp(float target, int time)
		{
			target = Math.Max(0f, target);
			target = Math.Min(Scale, target);
			rampInitValue = SetPoint;
			rampTime = time;
			rampTarget = target;
			rampTimer.Start(rampTime);
		}

		public void StopRamp()
		{
			Ramp(SetPoint, 0);
		}

		private void MonitorRamping()
		{
			if (rampTimer.IsTimeout() || rampTime == 0)
			{
				SetPoint = rampTarget;
			}
			else
			{
				SetPoint = (float)((double)rampInitValue + (double)(rampTarget - rampInitValue) * rampTimer.GetElapseTime() / (double)rampTime);
			}
		}

		protected virtual void MonitorTolerance()
		{
			CheckTolerance();
		}
	}
}
