using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.RecipeCenter;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.Utilities;
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 RinseThirdStepRoutine:RoutineBase,IRoutine
    {
        private enum RinseThirdStep
        {
            Recipe_StartThirdRinseCycle,
            Recipe_ThirdRinseStartFilling,
            Recipe_ThirdRinseRecordStartWaterLevel,
            Recipe_ThirdRinseStartFillingWait,
            Recipe_ThirdRinseWaitFillingDetected,
            Recipe_ThirdRinseWaitFull,
            Recipe_ThirdRinseWaitEndFillTime,
            Recipe_ThirdRinseWaitResistivityStart,
            Recipe_ThirdRinseResistivityAveraging,
            Recipe_ThirdRinseCheckResistivity,
            Recipe_StartThirdRinseClampCycle,
            Recipe_ThirdRinseWaitClampTime,
            Recipe_ThirdRinseCycleClampOff,
            Recipe_ThirdRinseCycleClampOn,
            Recipe_ThirdRinseCycleWaitSlowDrainTime,
            Recipe_ThirdRinseCycleEnd,
            Recipe_ThirdRinseWaitDrain,
            Recipe_ThirdRinseCheckDrain,
            Recipe_ThirdRinseWaitDrainExtraTime,
            Recipe_ThirdRinseComplete,
            Recipe_Complete,
        }
        #region 内部变量
        /// 
        /// 设备对象
        /// 
        private RinseDevice _device;
        /// 
        /// Recipe
        /// 
        private QdrRecipe _recipe;
        /// 
        /// Fill打开注水记录Water Level
        /// 
        private double _fillingDetectStartWaterLevel;
        /// 
        /// Concurrent Fill Time Seconds
        /// 
        private int _concurrentFillTimeSeconds;
        /// 
        /// 开始注水的偏差
        /// 
        private double _fillingStartedDelta;
        /// 
        /// 注满数值
        /// 
        private int _sensorReadingFull;
        /// 
        /// 液位为空数值
        /// 
        private int _sensorReadingEmpty;
        /// 
        /// 开始流水时间
        /// 
        private DateTime _startFillTime;
        /// 
        /// Clamp开关等待时间
        /// 
        private double _clampCycleTimeSeconds;
        /// 
        /// 从开始排水到检测是否排空的间隔时间
        /// 
        private int _normalDrainTimeSeconds;
        /// 
        /// Clamp Cycle开关次数
        /// 
        private int _numberClampCyclesToComplete;
        /// 
        /// Resistivity取值样本列表
        /// 
        private List _resistivitySample = new List();
        /// 
        /// 开始注水后检测是否正常注水间隔
        /// 
        private int _checkIsFillingTimeSeconds;
        /// 
        /// 开始注水后检测是否注满间隔
        /// 
        private int _checkIsFullTimeSeconds;
        /// 采样水阻值次数
        /// 
        private int _readResistivityCount = 0;
        /// 
        /// 当前执行到哪一步的显示
        /// 
        private string _currentStateMachine;
        /// 
        /// 开始采样时间
        /// 
        private DateTime _startSampleTime = DateTime.Now;
        /// 
        /// 采样时间
        /// 
        private DateTime _sampeIntervalTime = DateTime.Now;
        /// 
        /// 启动采样 
        /// 
        private bool _startSample = false;
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public RinseThirdStepRoutine(string module) : base(module)
        {
        }
        /// 
        /// 启动
        /// 
        /// 
        /// 
        public RState Start(params object[] objects)
        {
            _startSample = false;
            _resistivitySample.Clear();
            _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");
            _clampCycleTimeSeconds = SC.GetValue("QDR.ClampCycleTimeSeconds");
            _numberClampCyclesToComplete = SC.GetValue("QDR.NumberClampCyclesToComplete");
            _normalDrainTimeSeconds = SC.GetValue("QDR.NominalDrainTimeSeconds");
            _checkIsFillingTimeSeconds = SC.GetValue("QDR.NominalCheckFillWaterTimeSeconds");
            _checkIsFullTimeSeconds = SC.GetValue("QDR.NominalCheckFillFullTimeSeconds");
            //配置项规范性验证
            if (_checkIsFillingTimeSeconds + _checkIsFullTimeSeconds > _concurrentFillTimeSeconds)
            {
               NotifyError(eEvent.ERR_RINSE, $"configuration item 'QDR.NominalCheckFillWaterTimeSeconds' plus 'QDR.NominalCheckFillFullTimeSeconds' is large than QDR.ConcurrentFillTimeSeconds", 0);
                return RState.Failed;
            }
            if (_normalDrainTimeSeconds > _recipe.DumpTimeSeconds)
            {
               NotifyError(eEvent.ERR_RINSE, $"configuration item 'QDR.NominalDrainTimeSeconds' is large than 'recipe.DumpTimeSeconds",0);
                return RState.Failed;
            }
            return Runner.Start(Module, "Start Rinse Third Step");
        }
        /// 
        /// 监控
        /// 
        /// 
        public RState Monitor()
        {
            _currentStateMachine = Runner.CurrentStep.ToString();
            _device.UpdateStateMachine(_currentStateMachine);
            //3.6-StartThirdRinseCycle
            Runner.Run(RinseThirdStep.Recipe_StartThirdRinseCycle, OpenN2ValveAndCloseDumpValve, _delay_1ms)
                   //3.7-ThirdRinseStartFilling
                  .Run(RinseThirdStep.Recipe_ThirdRinseStartFilling, () => _device.FillValveOn(), _delay_1ms)
                  .Run(RinseThirdStep.Recipe_ThirdRinseRecordStartWaterLevel, CheckFillValveOn, _delay_1ms)
                  .RunDelay(RinseThirdStep.Recipe_ThirdRinseStartFillingWait, CheckFillNormalStatus, _checkIsFillingTimeSeconds *1000)
                  //3.8-ThirdRinseWaitFillingDetected and 3.9-ThirdRinseWaitFull
                  .RunDelay(RinseThirdStep.Recipe_ThirdRinseWaitFillingDetected,  CheckFillFullStatus, _checkIsFullTimeSeconds *1000)
                   //.Run(RinseThirdStep.Recipe_ThirdRinseWaitFull, CheckFillFullStatus, _delay_1s)
                   //4.0-ThirdRinseWaitEndFillTime
                  .Delay(RinseThirdStep.Recipe_ThirdRinseWaitEndFillTime, (_concurrentFillTimeSeconds - _checkIsFillingTimeSeconds - _checkIsFullTimeSeconds) * 1000)
                   //4.1-ThirdRinseWaitResistivityStart
                  .Run(RinseThirdStep.Recipe_ThirdRinseWaitResistivityStart, ResistivityStart, _recipe.ResistivityStartTimeSeconds*1000)
                   //4.2-ThirdRinseResistivityAveraging
                  .Run(RinseThirdStep.Recipe_ThirdRinseResistivityAveraging, ResistivityAveraging,_delay_1ms)
                   //4.3-ThirdRinseCheckResistivity
                  .Wait(RinseThirdStep.Recipe_ThirdRinseCheckResistivity, ResitivitySampleResitivity, _recipe.ResistivityDurationSeconds * 1000)
                   //4.4-ThirdRinseWaitClampTime
                  .Delay(RinseThirdStep.Recipe_ThirdRinseWaitClampTime, (_recipe.FinalRinsePulseClampTime - _recipe.ResistivityStartTimeSeconds - _recipe.ResistivityDurationSeconds) * 1000)
                  .LoopStart(RinseThirdStep.Recipe_StartThirdRinseClampCycle, "Clamp On/Off Cycle", _numberClampCyclesToComplete, NullFun, _delay_1ms)
                   //4.5-ThirdRinseCycleClampOff
                  .LoopRun(RinseThirdStep.Recipe_ThirdRinseCycleClampOff, () =>  _device.WaferHolderClampValveOff(), (int)_clampCycleTimeSeconds*1000)
                   //4.6-ThirdRinseCycleClampOn
                  .LoopRun(RinseThirdStep.Recipe_ThirdRinseCycleClampOn, () =>  _device.WaferHolderClampValveOn(), (int)_clampCycleTimeSeconds * 1000)
                  .LoopEnd(RinseThirdStep.Recipe_ThirdRinseCycleEnd, NullFun, _delay_1ms)
                   //4.8-ThirdRinseCycleWaitSlowDrainTime
                   .Delay(RinseThirdStep.Recipe_ThirdRinseCycleWaitSlowDrainTime,(_recipe.FinalRinseSlowDrainTime - (int)_clampCycleTimeSeconds * 2 * _numberClampCyclesToComplete) * 1000)
                   //4.9-ThirdRinseWaitDrain
                  .Run(RinseThirdStep.Recipe_ThirdRinseWaitDrain, StartOpenDumpValve, _delay_1ms)
                  .RunDelay(RinseThirdStep.Recipe_ThirdRinseCheckDrain, CheckWaterLevelEmpty, _normalDrainTimeSeconds * 1000)
                   //5.0-ThirdRinseWaitDrainExtraTime
                  .RunIf(RinseThirdStep.Recipe_ThirdRinseWaitDrainExtraTime, _recipe.DumpTimeSeconds - _normalDrainTimeSeconds > 0, NullFun, (_recipe.DumpTimeSeconds - _normalDrainTimeSeconds) * 1000)
                   //5.1-Recipe_Complete
                  .Run(RinseThirdStep.Recipe_ThirdRinseComplete, () => _device.WasteValveOff(), _delay_1ms)
                  .End(RinseThirdStep.Recipe_Complete, NullFun, _delay_1ms);
             return Runner.Status;
        }
        /// 
        /// 启动N2和关闭Dump Valve
        /// 
        /// 
        private bool OpenN2ValveAndCloseDumpValve()
        {
            bool result = true;
            if (_recipe.Step2N2BubbleOn)
            {
                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;
            return (currentWaterLevel - _fillingDetectStartWaterLevel) > _fillingStartedDelta;
        }
        /// 
        /// 检验是否注满
        /// 
        /// 
        private bool CheckFillFullStatus()
        {
            double currentWaterLevel = _device.RinseData.WaterLevel;
            bool result = currentWaterLevel > _sensorReadingFull;
            return result;
        }
        /// 
        /// 打开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 Valve 
        /// 
        /// 
        private void CheckNeedCloseMetalDrain()
        {
            //此时已经冲洗的次数包括第一步加第二步加第三步的一次
            if (_recipe.Step1NumberOfRinse + _recipe.Step2NumberOfRinse + 1 > _recipe.Step1NumberOfDumpToMetalDrain)
            {
                bool result = _device.WasteValveOn();
                if (!result)
                {
                   NotifyError(eEvent.ERR_RINSE, "Close Metal Drain Valve error", 0);
                }
            }
        }
        /// 
        /// ResistivityStart
        /// 
        /// 
        private bool ResistivityStart()
        {
            bool result = true;
            result = _device.FillValveOff();
            if (!result)
            {
               NotifyError(eEvent.ERR_RINSE, "Fill Valve Off error",0);
                return false;
            }
            if (_recipe.Step2N2BubbleOn)
            {
                result = _device.N2ValveOff();
                if (!result)
                {
                   NotifyError(eEvent.ERR_RINSE, "N2 Valve Off error", 0);
                    return false;
                }
            }
            return result;
        }
        /// 
        /// ResistivityAveraging
        /// 
        /// 
        private bool ResistivityAveraging()
        {
            if (_recipe.ResistivityDurationSeconds == 0)
            {
                _resistivitySample.Add(GetResitivity());
            }
            else
            {
                _startSampleTime = DateTime.Now;
                _sampeIntervalTime = DateTime.Now;
                _startSample = true;
            }
            return true;
        }
        /// 
        /// 采样Resitivity
        /// 
        /// 
        private bool ResitivitySampleResitivity()
        {
            if (!_startSample)
            {
                return true;
            }
            int sampleTotalCount = (int)Math.Ceiling(_recipe.ResistivityDurationSeconds / 0.1);
            //每隔100毫秒采样
            if (DateTime.Now.Subtract(_sampeIntervalTime).TotalMilliseconds >= 100)
            {
                _sampeIntervalTime = DateTime.Now;
                _readResistivityCount++;
                _resistivitySample.Add(GetResitivity());
            }
            //ResistivityDurationSeconds时长减去0.1s,避免超时
            if (DateTime.Now.Subtract(_startSampleTime).TotalMilliseconds >= _recipe.ResistivityDurationSeconds * 1000 - 100)
            {
                bool result = CheckResistivity();
                if (!result)
                {
                    Runner.Stop("Sample Resitiviy abormal", true);
                }
                return result;
            }
            return false;
        }
        //读取Resitivity的值
        private double GetResitivity()
        {
            double resistivity = 0;
            ResistivityController resistivityController = DEVICE.GetDevice(_device.RinseItem.ResistivityID);
            if (resistivityController != null)
            {
                try
                {
                    resistivity = double.Parse(resistivityController.ResisitivityValue.Trim());
                }
                catch 
                {
                    resistivity = 0;
                }
            }
            return resistivity;
        }
        /// 
        /// CheckResistivity
        /// 
        /// 
        private bool CheckResistivity()
        {
            if (_recipe.ResistivityMegaOhms == 0)
            {
                _resistivitySample.Clear();
                return true;
            }
            double resistivityAverageValue = _resistivitySample.Average();
            if ((_resistivitySample.Count == 1 && _resistivitySample[0] < _recipe.ResistivityMegaOhms) || resistivityAverageValue < _recipe.ResistivityMegaOhms)
            {
               NotifyError(eEvent.ERR_RINSE, $"The detected resistivity value is abnormal,: {resistivityAverageValue}",0);
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_RINSE, Module, $"The detected resistivity value is : {resistivityAverageValue}");
            }
            _resistivitySample.Clear();
            return true;
        }
        /// 
        /// Abort
        /// 
        public void Abort()
        {
            Runner.Stop("Manual abort");
        }
    }
}