using Aitex.Core.RT.Device;
using Aitex.Core.RT.IOCore;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.RecipeCenter;
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.Resistivity;
using CyberX8_RT.Devices.Rinse;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CyberX8_RT.Modules.Rinse
{
    public class RinseFirstStepRoutine : RoutineBase, IRoutine
    {
        private enum RinseFirstStep
        {
            StartPrepare,
            FirstDrain,
            CheckDrain,
            WaitDrianEmpty,
            N2BubbleOn,
            N2BubbleOnDelay,
            Recipe_StartFirstRinseCycle,
            Recipe_PerformFirstRinseCycle,
            Recipe_FirstRinseCycleStartFilling,
            Recipe_FirstRinseCycleRecordStartWaterLevel,
            Recipe_FirstRinseCycleStartFillingWait,
            Recipe_FirstRinseCycleWaitFillingDetected,
            Recipe_FirstRinseCycleWaitFull,
            Recipe_FirstRinseCycleWaitEndFillTime,
            Recipe_FirstRinseCycleWaitDwell,
            Recipe_FirstRinseCycleWaitDrain,
            Recipe_FirstRinseCycleCheckDrain,
            Recipe_FirstRinseCycleWaitDrainExtraTime,
            Recipe_FirstRinseCycleEnd,
            Recipe_FirstRinseCycleComplete
        }
        #region 内部变量
        /// 
        /// 设备对象
        /// 
        private RinseDevice _device;
        /// 
        /// Recipe
        /// 
        private QdrRecipe _recipe;
        /// 
        /// Fill打开注水记录Water Level
        /// 
        private double _fillingDetectStartWaterLevel;
        /// 
        /// 配置文件中注水整个过程的耗时
        /// 
        private int _concurrentFillTimeSeconds;
        /// 
        /// 开始注水的偏差
        /// 
        private double _fillingStartedDelta;
        /// 
        /// 注满数值
        /// 
        private int _sensorReadingFull;
        /// 
        /// 液位为空数值
        /// 
        private int _sensorReadingEmpty;
        /// 
        /// 开始流水时间
        /// 
        private DateTime _startFillTime;
        /// 
        /// 从开始排水到检测是否排空的间隔时间
        /// 
        private int _normalDrainTimeSeconds;
        /// 
        /// 开始注水后检测是否正常注水间隔
        /// 
        private int _checkIsFillingTimeSeconds;
        /// 
        /// 开始注水后检测是否注满间隔
        /// 
        private int _checkIsFullTimeSeconds;
        /// 
        /// 当前执行到哪一步的显示
        /// 
        private string _currentStateMachine;
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public RinseFirstStepRoutine(string module) : base(module)
        {
        }
        /// 
        /// 启动
        /// 
        /// 
        /// 
        public RState Start(params object[] objects)
        {
            _device = DEVICE.GetDevice(Module);
            _recipe = objects[0] as QdrRecipe;
            _concurrentFillTimeSeconds = SC.GetValue("QDR.ConcurrentFillTimeSeconds");
            _fillingStartedDelta = SC.GetValue("QDR.FillingStartedDelta");
            _sensorReadingFull = SC.GetValue("QDR.SensorReadingFull");
            _sensorReadingEmpty = SC.GetValue("QDR.SensorReadingEmpty");
            _normalDrainTimeSeconds = SC.GetValue("QDR.NominalDrainTimeSeconds");
            _checkIsFillingTimeSeconds = SC.GetValue("QDR.NominalCheckFillWaterTimeSeconds");
            _checkIsFullTimeSeconds = SC.GetValue("QDR.NominalCheckFillFullTimeSeconds");
            _fillingDetectStartWaterLevel = 0;
            //配置项规范性验证
            if (_checkIsFillingTimeSeconds + _checkIsFullTimeSeconds > _concurrentFillTimeSeconds)
            {
                NotifyError(eEvent.ERR_RINSE, $"configuration item 'QDR.NominalCheckFillWaterTimeSeconds' plus 'QDR.NominalCheckFillFullTimeSeconds' is large than QDR.ConcurrentFillTimeSeconds",-1);
                return RState.Failed;
            }
            if (_normalDrainTimeSeconds > _recipe.DumpTimeSeconds)
            {
                NotifyError(eEvent.ERR_RINSE, $"configuration item 'QDR.NominalDrainTimeSeconds' is large than 'recipe.DumpTimeSeconds",-1);
                return RState.Failed;
            }
            return Runner.Start(Module, "Start Rinse First Step");
        }
        /// 
        /// Abort
        /// 
        public void Abort()
        {           
            Runner.Stop("Manual abort");
        }
        /// 
        /// 监控
        /// 
        /// 
        public RState Monitor()
        {
            _currentStateMachine = Runner.CurrentStep.ToString();
            _device.UpdateStateMachine(_currentStateMachine);
                //1.2-Start
            Runner.Run(RinseFirstStep.StartPrepare,StartPrepareAction, _delay_1ms)
                //1.3-WatiDrained
               .Run(RinseFirstStep.FirstDrain,OpenDrainValveandCheckMetalValve, _delay_1ms)
               .RunDelay(RinseFirstStep.CheckDrain, CheckWaterLevelEmpty, _normalDrainTimeSeconds*1000)
                //1.4-ExtraDrainDeylay
               .RunIf(RinseFirstStep.WaitDrianEmpty, _recipe.DumpTimeSeconds - _normalDrainTimeSeconds > 0, NullFun ,(_recipe.DumpTimeSeconds - _normalDrainTimeSeconds) * 1000)
                //1.5-N2PreCharge
               .RunIf(RinseFirstStep.N2BubbleOn, _recipe.Step1N2BubbleOn, N2ValveOn, _delay_1ms) 
               .RunIf(RinseFirstStep.N2BubbleOnDelay, _recipe.Step1N2BubbleOn, NullFun, _recipe.N2ChargeTimeSeconds*1000)
                //1.6-StartFirstRinseCylce
               .LoopStart(RinseFirstStep.Recipe_StartFirstRinseCycle, "Rinse first step", _recipe.Step1NumberOfRinse, PrepareStart, _delay_1ms)
               //1.7-PerformFirstRinseCycle
               .LoopRun(RinseFirstStep.Recipe_PerformFirstRinseCycle,OpenN2ValveAndCloseDumpValve,_delay_1ms)
                //1.8-FirstRinseCycleStartFilling
               .LoopRun(RinseFirstStep.Recipe_FirstRinseCycleStartFilling, () => _device.FillValveOn(), _delay_1ms)
               .LoopRun(RinseFirstStep.Recipe_FirstRinseCycleRecordStartWaterLevel,  CheckFillValveOn, _delay_1ms)
               .LoopRunOnlyTimeOutFault(RinseFirstStep.Recipe_FirstRinseCycleStartFillingWait, CheckFillNormalStatus, _checkIsFillingTimeSeconds * 1000)
                //1.9-FirstRinseCycleWaitFillingDetected  and 2.0-FirstRinseCycleWaitFull
               .LoopRunOnlyTimeOutFault(RinseFirstStep.Recipe_FirstRinseCycleWaitFillingDetected, CheckFillFullStatus, _checkIsFullTimeSeconds * 1000)
                //2.1-FirstRinseCycleWaitEndFillTime
               .LoopDelay(RinseFirstStep.Recipe_FirstRinseCycleWaitEndFillTime, (_concurrentFillTimeSeconds - _checkIsFillingTimeSeconds- _checkIsFullTimeSeconds) * 1000)
                //2.2-FirstRinseCycleWaitDwell
               .LoopRunDelay(RinseFirstStep.Recipe_FirstRinseCycleWaitDwell, StartDwell, _recipe.Step1DwellTimeSeconds * 1000)
                //2.3-FirstRinseCycleWaitDrain 
               .LoopRun(RinseFirstStep.Recipe_FirstRinseCycleWaitDrain, StartOpenDumpValve,_delay_1ms)
               .LoopRunOnlyTimeOutFault(RinseFirstStep.Recipe_FirstRinseCycleCheckDrain,CheckWaterLevelEmpty, _normalDrainTimeSeconds * 1000)
                //2.4-FirstRinseCycleWaitDrainExtraTime
               .LoopRunIf(RinseFirstStep.Recipe_FirstRinseCycleWaitDrainExtraTime, _recipe.DumpTimeSeconds - _normalDrainTimeSeconds > 0,NullFun, (_recipe.DumpTimeSeconds - _normalDrainTimeSeconds) * 1000 )
               .LoopEnd(RinseFirstStep.Recipe_FirstRinseCycleEnd, NullFun, _delay_1ms)
               .End(RinseFirstStep.Recipe_FirstRinseCycleComplete, NullFun, _delay_1ms);
            return Runner.Status;
        }
        /// 
        /// Close Fill valve 和 Clamp valve
        /// 
        /// 
        private bool StartPrepareAction()
        {
            bool result = _device.FillValveOff();
            if (!result)
            {
                NotifyError(eEvent.ERR_RINSE, "Close Fill Valve error",0);
                return false;
            }
            result = _device.WaferHolderClampValveOn();
            if (!result)
            {
                NotifyError(eEvent.ERR_RINSE, "Open Clamp Valve error", 0);
                return false;
            }
            return result;
        }
        /// 
        /// 打开排水阀并且检查是否需要打开metal drain valve
        /// 
        /// 
        private bool OpenDrainValveandCheckMetalValve()
        {
            bool result = _device.DrainValveOn();
            if (!result)
            {
                NotifyError(eEvent.ERR_RINSE, "Open Drain Valve error",0);
                return false;
            }
            if (_recipe.Step1NumberOfDumpToMetalDrain > 0)
            {
                result = _device.WasteValveOff();
                if (!result)
                {
                    NotifyError(eEvent.ERR_RINSE, "Open Metal Valve error", 0);
                    return false;
                }
            }
            return result;
        }
        /// 
        /// N2 Valve On
        /// 
        /// 
        private bool N2ValveOn()
        {
            return _device.N2ValveOn();
        }
        /// 
        /// 检验N2Valve on
        /// 
        /// 
        private bool CheckN2ValveOn()
        {
            return _device.RinseData.N2Valve;
        }
        /// 
        /// 准备启动
        /// 
        /// 
        private bool PrepareStart()
        {
            if (_recipe.Step1N2BubbleOn)
            {
                return _device.N2ValveOff();
            }
            return true;
        }
        /// 
        /// 启动N2和关闭Dump Valve
        /// 
        /// 
        private bool OpenN2ValveAndCloseDumpValve()
        {
            bool result = true;
            if(_recipe.Step1N2BubbleOn)
            {
                result = _device.N2ValveOn();
                if(!result)
                {
                    NotifyError(eEvent.ERR_RINSE, "Open N2 Valve error",0);
                    return false;
                }
            }
            result = _device.DrainValveOff();
            if(!result)
            {
                NotifyError(eEvent.ERR_RINSE, "Close Dump Valve error", 0);
            }
            return result;
        }
        /// 
        /// 检验Fill Valve打开状态
        /// 
        /// 
        private bool CheckFillValveOn()
        {
            _startFillTime = DateTime.Now;
            _fillingDetectStartWaterLevel = _device.RinseData.WaterLevel;
            return true;
        }
        /// 
        /// 检验是否正常流水
        /// 
        /// 
        private bool CheckFillNormalStatus()
        {
            double currentWaterLevel = _device.RinseData.WaterLevel;
            bool result =(currentWaterLevel-_fillingDetectStartWaterLevel)>_fillingStartedDelta;
            return result;
        }
        /// 
        /// 检验是否注满
        /// 
        /// 
        private bool CheckFillFullStatus()
        {
            double currentWaterLevel = _device.RinseData.WaterLevel;
            bool result= currentWaterLevel > _sensorReadingFull;
            return result;
        }
        /// 
        /// 开始Dwell
        /// 
        /// 
        private bool StartDwell()
        {
            bool result = _device.FillValveOff();
            if(!result)
            {
                NotifyError(eEvent.ERR_RINSE, "Fill Valve off error",0);
                return false;
            }
            if(_recipe.Step1N2BubbleOn)
            {
                result = _device.N2ValveOff();
                if(!result)
                {
                    NotifyError(eEvent.ERR_RINSE, "N2 Valve off error", 0);
                    return false;
                }
            }
            return true;
        }
        /// 
        /// 打开Dump Valve
        /// 
        /// 
        private bool StartOpenDumpValve()
        {
            CheckNeedCloseMetalDrain();
            bool result = _device.DrainValveOn();
            if(!result)
            {
                NotifyError(eEvent.ERR_RINSE, "Open Dump valve error",0);
                return false;
            }
            return result;
        }
        /// 
        /// 检验快排是否排空
        /// 
        /// 
        private bool CheckWaterLevelEmpty()
        {
            double currentWaterLevel = _device.RinseData.WaterLevel;
            bool reseult = currentWaterLevel < _sensorReadingEmpty;
            if (!reseult)
            {
                NotifyError(eEvent.ERR_RINSE, $"current water level: {currentWaterLevel} is large than sensorReadingEmpty: {_sensorReadingEmpty}", 0);
            }
            return reseult;
        }
        /// 
        /// 检验是否需要关闭Metal Valve20
        /// 
        /// 
        private void CheckNeedCloseMetalDrain()
        {
            if (Runner.LoopCounter + 1>_recipe.Step1NumberOfDumpToMetalDrain)
            {
                bool result = _device.WasteValveOn();
                if (!result)
                {
                    NotifyError(eEvent.ERR_RINSE, "Close Metal Drain Valve error", 0);
                }
            }
        }
    }
}