using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.Routine;
using CyberX8_Core;
using CyberX8_RT.Devices.Dryer;
using System.Collections.Generic;
using MECF.Framework.Common.CommonData.Dryer;
using MECF.Framework.Common.CommonData;
using MECF.Framework.Common.Alarm;
namespace CyberX8_RT.Modules.Dryer
{
    public class DryerRunRecipeRoutine : RoutineBase, IRoutine
    {
        #region step enum
        /// 
        /// 步骤枚举
        /// 
        private enum DryerRunRecipeStep
        {
            ControlPowerOn,
            HighOn,
            Delay,
            CheckPressureMinimum,
            DelayCheckPressureWarning,
            CheckPressureWarning,
            DelayCheckPressureError,
            CheckPressureError,
            DelayRecipeTime,
            LowerOn,
            End
        }
        #endregion
        #region 常量
        private const int PRESSURE_DELAY = 500;
        
        private const string EXHAUST_PRESSURE = "ExhaustPressure";
        #endregion
        #region 内部变量
        /// 
        /// 设备对象
        /// 
        private DryerDevice _device;
        /// 
        /// HVD Recipe
        /// 
        public HvdRecipe _hvdRecipe;
        /// 
        /// minimum pressure
        /// 
        private double _minimumPressure = 0;
        /// 
        /// Check Pressure Warning Delay Second
        /// 
        private int _pressureCheckWarningHoldoffSeconds;
        /// 
        /// Warning Pressure value
        /// 
        private double _pressureCheckWarningMMHG;
        /// 
        /// Check Pressure Error Delay Second
        /// 
        private int _pressureCheckErrorHoldoffSeconds;
        /// 
        /// Error Pressure value
        /// 
        private double _pressureCheckErrorMMHG;
        /// 
        /// recipe时长
        /// 
        private int _dryProcessTime;
        /// 
        /// recipe里的DryTime时长
        /// 
        public int _recipeDrytime;      
        
        #endregion
        #region 属性
        /// 
        /// HVD Recipe
        /// 
        public HvdRecipe HvdRecipe { get { return _hvdRecipe; } }
        /// 
        /// LotTrack数据
        /// 
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public DryerRunRecipeRoutine(string module) : base(module)
        {
        }        
        /// 
        /// 中止
        /// 
        public void Abort()
        {
            Runner.Stop("Manual abort dryer run recipe");
            _device.BlowerLowOn();
        }
        /// 
        /// 监控
        /// 
        /// 
        public RState Monitor()
        {
            Runner.Run(DryerRunRecipeStep.ControlPowerOn, () => _device.PowerControlOn(), () => { return _device.CommonData.PowerControl; }, _delay_1s)
                .Run(DryerRunRecipeStep.HighOn, () => _device.BlowerHighOn(),()=> { return _device.CommonData.BlowerHigh; }, _delay_1s)
                .DelayIf(DryerRunRecipeStep.Delay,!_device.Bypass,PRESSURE_DELAY)
                .RunIf(DryerRunRecipeStep.CheckPressureMinimum, !_device.Bypass, CheckPressureMinimum,_delay_1ms)
                .Delay(DryerRunRecipeStep.DelayCheckPressureWarning, _pressureCheckWarningHoldoffSeconds * 1000)
                .Run(DryerRunRecipeStep.CheckPressureWarning, CheckPressureWaring, _delay_1ms)
                .Delay(DryerRunRecipeStep.DelayCheckPressureError, _pressureCheckErrorHoldoffSeconds * 1000)
                .Run(DryerRunRecipeStep.CheckPressureError, CheckPressureError, _delay_1ms)
                .Delay(DryerRunRecipeStep.DelayRecipeTime, _dryProcessTime)
                .Run(DryerRunRecipeStep.LowerOn, () => _device.BlowerLowOn(), _delay_1ms)
                .End(DryerRunRecipeStep.End, NullFun, _delay_1ms);
            return Runner.Status;
        }
        /// 
        /// 检验Minimum Pressure
        /// 
        /// 
        private bool CheckPressureMinimum()
        {
            double pressure = _device.CommonData.ExhaustPressure;
            if(pressure>=_minimumPressure)
            {
                NotifyError(eEvent.ERR_DRYER, $"{pressure} is over minimum pressure {_minimumPressure}", 0);
                _device.BlowerLowOn();
                return false;
            }
            return true;
        }
        /// 
        /// 检验Pressure是否低于Waring
        /// 
        /// 
        private bool CheckPressureWaring()
        {
            double pressure = _device.CommonData.ExhaustPressure;
            if(pressure > _pressureCheckWarningMMHG && pressure <= _pressureCheckErrorMMHG)
            {
                string str = $"{pressure} is large than waring pressure {_pressureCheckWarningMMHG}";
                if (AlarmListManager.Instance.AddWarn(Module, "Exhaust Pressure",str))
                {
                    LOG.WriteLog(eEvent.WARN_DRYER, Module,str);
                }
            }
            return true;
        }
        /// 
        /// 检验Pressure是否低于Error
        /// 
        /// 
        private bool CheckPressureError()
        {
            double pressure = _device.CommonData.ExhaustPressure;
            if (pressure > _pressureCheckErrorMMHG)
            {
                NotifyError(eEvent.ERR_DRYER, $"{pressure} is large than error pressure {_pressureCheckErrorMMHG}",0);
                _device.BlowerLowOn();
                return false;
            }
            return true;
        }       
        /// 
        /// 启动
        /// 
        /// 
        /// 
        public RState Start(params object[] objects)
        {
            _hvdRecipe = objects[0] as HvdRecipe;
            if (_hvdRecipe == null)
            {
                NotifyError(eEvent.ERR_DRYER, "recipe is null",-1);
                return RState.Failed;
            }
            _device = DEVICE.GetDevice(Module);
            _recipeDrytime = _hvdRecipe.DryTime;
            _pressureCheckWarningHoldoffSeconds = SC.GetValue("Dryer.PressureCheckWarningHoldoffSeconds");
            _pressureCheckWarningMMHG = SC.GetValue("Dryer.PressureCheckWarningMMHG");
            _pressureCheckErrorHoldoffSeconds = SC.GetValue("Dryer.PressureCheckErrorHoldoffSeconds");
            _pressureCheckErrorMMHG = SC.GetValue("Dryer.PressureCheckErrorMMHG");
            _minimumPressure = SC.GetValue("Dryer.MinimumPressure");
            int dryRecipeTime = _hvdRecipe.DryTime*1000;
            int processTime= dryRecipeTime-PRESSURE_DELAY- _pressureCheckWarningHoldoffSeconds*1000- _pressureCheckErrorHoldoffSeconds*1000;
            if(processTime>0)
            {
                _dryProcessTime = processTime;
            }
            else
            {
                _dryProcessTime = 1;
            }
            
            return Runner.Start(Module, "Start run dryer recipe");
        }
    }
}