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.ToolLayout;
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;
using System.Windows.Documents;

namespace CyberX8_RT.Modules.Rinse
{
    public class RinseSecondStepRoutine:RoutineBase,IRoutine
    {
        private enum RinseSecondStep
        {
            PrepareStart,
            Recipe_StartSecondRinseCycle,
            Recipe_PerformSecondRinseCycle,
            Recipe_SecondRinseCycleStartFilling,
            Recipe_SecondRinseCycleRecordStartWaterLevel,
            Recipe_SecondRinseCycleStartFillingWait,
            Recipe_SecondRinseCycleWaitFillingDetected,
            Recipe_SecondRinseCycleWaitFull,
            Recipe_SecondRinseCycleWaitEndFillTime,
            Recipe_SecondRinseCycleWaitDwell,
            Recipe_SecondRinseCycleWaitDrain,
            Recipe_SecondRinseCycleCheckDrain,
            Recipe_SecondRinseCycleWaitDrainExtraTime,
            Recipe_SecondRinseCycleWaitResistivityStart,
            Recipe_SecondRinseCycleResistivityAveraging,
            Recipe_SecondRinseCycleCheckResistivity,
            Recipe_SecondRinseCycleWaitDrain2,
            Recipe_SecondRinseCycleCheckDrain2,
            Recipe_SecondRinseCycleWaitDrain2ExtraTime,
            Recipe_SecondRinseCycleEnd,
            Recipe_SecondRinseCycleComplete
        }

        #region 内部变量
        /// <summary>
        /// 设备对象
        /// </summary>
        private RinseDevice _device;
        /// <summary>
        /// Recipe
        /// </summary>
        private QdrRecipe _recipe;
        /// <summary>
        /// Fill打开注水记录Water Level
        /// </summary>
        private double _fillingDetectStartWaterLevel;
        /// <summary>
        /// Concurrent Fill Time Seconds
        /// </summary>
        private int _concurrentFillTimeSeconds;
        /// <summary>
        /// 开始注水的偏差
        /// </summary>
        private double _fillingStartedDelta;
        /// <summary>
        /// 注满数值
        /// </summary>
        private int _sensorReadingFull;
        /// <summary>
        /// 液位为空数值
        /// </summary>
        private int _sensorReadingEmpty;
        /// <summary>
        /// 开始流水时间
        /// </summary>
        private DateTime _startFillTime;
        /// <summary>
        /// 从开始排水到检测是否排空的间隔时间
        /// </summary>
        private int _normalDrainTimeSeconds;
        /// <summary>
        /// 表示当前正在执行第几次rinse
        /// </summary>
        private int _rinseCycleTwo_RinsesCompleted = 0;
        /// <summary>
        /// Resistivity取值样本列表
        /// </summary>
        private List<double> _resistivitySample = new List<double>();
        /// <summary>
        /// 开始注水后检测是否正常注水间隔
        /// </summary>
        private int _checkIsFillingTimeSeconds;
        /// <summary>
        /// 开始注水后检测是否注满间隔
        /// </summary>
        private int _checkIsFullTimeSeconds;
        /// <summary>
        /// 采样水阻值次数
        /// </summary>
        private int _readResistivityCount = 0;
        /// <summary>
        /// 当前执行到哪一步的显示
        /// </summary>
        private string _currentStateMachine;
        /// <summary>
        /// 开始采样时间
        /// </summary>
        private DateTime _startSampleTime = DateTime.Now;
        /// <summary>
        /// 采样时间
        /// </summary>
        private DateTime _sampeIntervalTime = DateTime.Now;
        /// <summary>
        /// 启动采样 
        /// </summary>
        private bool _startSample = false;
        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="module"></param>
        public RinseSecondStepRoutine(string module) : base(module)
        {
            
        }
        /// <summary>
        /// 启动
        /// </summary>
        /// <param name="objects"></param>
        /// <returns></returns>
        public RState Start(params object[] objects)
        {
            _startSample = false;
            _device = DEVICE.GetDevice<RinseDevice>(Module);
            _resistivitySample.Clear();
            _readResistivityCount = 0;
            _recipe = objects[0] as QdrRecipe;
            _concurrentFillTimeSeconds = SC.GetValue<int>("QDR.ConcurrentFillTimeSeconds");
            _fillingStartedDelta = SC.GetValue<double>("QDR.FillingStartedDelta");
            _sensorReadingFull = SC.GetValue<int>("QDR.SensorReadingFull");
            _sensorReadingEmpty = SC.GetValue<int>("QDR.SensorReadingEmpty");
            _normalDrainTimeSeconds = SC.GetValue<int>("QDR.NominalDrainTimeSeconds");
            _checkIsFillingTimeSeconds = SC.GetValue<int>("QDR.NominalCheckFillWaterTimeSeconds");
            _checkIsFullTimeSeconds = SC.GetValue<int>("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 Second Step");
        }

        /// <summary>
        /// 监控
        /// </summary>
        /// <returns></returns>
        public RState Monitor()
        {
            _currentStateMachine = Runner.CurrentStep.ToString();
            _device.UpdateStateMachine(_currentStateMachine);
            Runner.RunIf(RinseSecondStep.PrepareStart, _recipe.Step2N2BubbleOn, N2ValveOff, _delay_1ms)
                 //2.6-StartSecondRinseCycle
                .LoopStart(RinseSecondStep.Recipe_StartSecondRinseCycle, "Rinse Second step", _recipe.Step2NumberOfRinse, NullFun, _delay_1ms)
                 //2.7-PerformSecondRinseCycle
                .LoopRun(RinseSecondStep.Recipe_PerformSecondRinseCycle, OpenN2ValveAndCloseDumpValve, _delay_1ms)
                 //2.8-SecondRinseCycleStartFilling
                .LoopRun(RinseSecondStep.Recipe_SecondRinseCycleStartFilling, () => _device.FillValveOn(), _delay_1ms)
                .LoopRun(RinseSecondStep.Recipe_SecondRinseCycleRecordStartWaterLevel, CheckFillValveOn, _delay_1ms)
                .LoopRunOnlyTimeOutFault(RinseSecondStep.Recipe_SecondRinseCycleStartFillingWait, CheckFillNormalStatus, _checkIsFillingTimeSeconds * 1000)
                 //2.9-SecondRinseCycleWaitFillingDetected  //3.0-SecondRinseCycleWaitFull
                .LoopRunOnlyTimeOutFault(RinseSecondStep.Recipe_SecondRinseCycleWaitFillingDetected, CheckFillFullStatus, _checkIsFullTimeSeconds * 1000)
                 //.LoopRun(RinseSecondStep.Recipe_SecondRinseCycleWaitFull, CheckFillFullStatus, _delay_1s)
                 //3.1-SecondRinseCycleWaitEndFillTime
                .LoopDelay(RinseSecondStep.Recipe_SecondRinseCycleWaitEndFillTime, (_concurrentFillTimeSeconds - _checkIsFillingTimeSeconds - _checkIsFullTimeSeconds) * 1000)
                 //3.2-SecondRinseCycleWaitDwell  
                .LoopRunIf(RinseSecondStep.Recipe_SecondRinseCycleWaitDwell, ((_rinseCycleTwo_RinsesCompleted < _recipe.Step2NumberOfRinse - 1) && !_recipe.FinalRinseDry)
                                          || ((_rinseCycleTwo_RinsesCompleted < _recipe.Step2NumberOfRinse) && _recipe.FinalRinseDry), 
                                          StartDwell, _recipe.Step2DwellTimeSeconds * 1000)
                 //3.3-SecondRinseCycleWaitDrain
                .LoopRunIf(RinseSecondStep.Recipe_SecondRinseCycleWaitDrain, ((_rinseCycleTwo_RinsesCompleted < _recipe.Step2NumberOfRinse - 1) && !_recipe.FinalRinseDry)
                                          || ((_rinseCycleTwo_RinsesCompleted < _recipe.Step2NumberOfRinse) && _recipe.FinalRinseDry),
                                          StartOpenDumpValve, _delay_1ms)
                .LoopRunIfOnlyTimeOutFault(RinseSecondStep.Recipe_SecondRinseCycleCheckDrain, ((_rinseCycleTwo_RinsesCompleted < _recipe.Step2NumberOfRinse - 1) && !_recipe.FinalRinseDry)
                                          || ((_rinseCycleTwo_RinsesCompleted < _recipe.Step2NumberOfRinse) && _recipe.FinalRinseDry),
                                          CheckWaterLevelEmpty, _normalDrainTimeSeconds * 1000)
                //3.4-SecondRinseCycleWaitDrainExtraTime
                .LoopRunIf(RinseSecondStep.Recipe_SecondRinseCycleWaitDrainExtraTime, ((_rinseCycleTwo_RinsesCompleted < _recipe.Step2NumberOfRinse - 1) && !_recipe.FinalRinseDry && _recipe.DumpTimeSeconds - _normalDrainTimeSeconds > 0)
                                          || ((_rinseCycleTwo_RinsesCompleted < _recipe.Step2NumberOfRinse) && _recipe.FinalRinseDry && _recipe.DumpTimeSeconds - _normalDrainTimeSeconds > 0),
                                          NullFun, (_recipe.DumpTimeSeconds - _normalDrainTimeSeconds) * 1000)
                //3.7-SecondRinseCycleWaitResistivityStart   条件:(Final Rinse == false && RinseComplete ==  _recipe.Step2NumberOfRinse - 1)
                .LoopRunIf(RinseSecondStep.Recipe_SecondRinseCycleWaitResistivityStart, (_rinseCycleTwo_RinsesCompleted == _recipe.Step2NumberOfRinse - 1) && !_recipe.FinalRinseDry,
                                          ResistivityStart, _recipe.ResistivityStartTimeSeconds*1000)
                 //3.8-SecondRinseCycleResistivityAveraging   条件:(Final Rinse == false && RinseComplete ==  _recipe.Step2NumberOfRinse - 1)
                .LoopRunIf(RinseSecondStep.Recipe_SecondRinseCycleResistivityAveraging, (_rinseCycleTwo_RinsesCompleted == _recipe.Step2NumberOfRinse - 1) && !_recipe.FinalRinseDry,
                                          ResistivityAveraging, _delay_1ms)
                //3.9-SecondRinseCycleCheckResistivity   条件:(Final Rinse == false && RinseComplete ==  _recipe.Step2NumberOfRinse - 1)
                .LoopWaitIf(RinseSecondStep.Recipe_SecondRinseCycleCheckResistivity, (_rinseCycleTwo_RinsesCompleted == _recipe.Step2NumberOfRinse - 1) && !_recipe.FinalRinseDry, 
                                          ResitivitySampleResitivity,_recipe.ResistivityDurationSeconds*1000) 
                 //4.0-SecondRinseCycleWaitDrain   条件:(Final Rinse == false && RinseComplete ==  _recipe.Step2NumberOfRinse - 1)
                .LoopRunIf(RinseSecondStep.Recipe_SecondRinseCycleWaitDrain2, (_rinseCycleTwo_RinsesCompleted == _recipe.Step2NumberOfRinse - 1) && !_recipe.FinalRinseDry,
                                          StartOpenDumpValve, _delay_1ms)
                .LoopRunIfOnlyTimeOutFault(RinseSecondStep.Recipe_SecondRinseCycleCheckDrain2, (_rinseCycleTwo_RinsesCompleted == _recipe.Step2NumberOfRinse - 1) && !_recipe.FinalRinseDry,
                                          CheckWaterLevelEmpty, _normalDrainTimeSeconds * 1000)
                //4.1-Recipe_SecondRinseCycleWaitDrain2ExtraTime   条件:(Final Rinse == false && RinseComplete ==  _recipe.Step2NumberOfRinse - 1)
                .LoopRunIf(RinseSecondStep.Recipe_SecondRinseCycleWaitDrain2ExtraTime, (_rinseCycleTwo_RinsesCompleted == _recipe.Step2NumberOfRinse - 1) && !_recipe.FinalRinseDry && _recipe.DumpTimeSeconds - _normalDrainTimeSeconds > 0,
                                          NullFun, (_recipe.DumpTimeSeconds - _normalDrainTimeSeconds) * 1000) 
                .LoopEnd(RinseSecondStep.Recipe_SecondRinseCycleEnd, CountNumberofRinsesComplete, _delay_1ms)
                .End(RinseSecondStep.Recipe_SecondRinseCycleComplete, ResetRinseComplete, _delay_1ms);
                return Runner.Status;
        }
        /// <summary>
        /// N2 Valve Off
        /// </summary>
        /// <returns></returns>
        private bool N2ValveOff()
        {
            if (_recipe.Step1N2BubbleOn)
            {
                return _device.N2ValveOff();
            }
            else
            {
                return true;
            }
        }
        /// <summary>
        /// 检验N2Valve off
        /// </summary>
        /// <returns></returns>
        private bool CheckN2ValveOff()
        {
            if (_recipe.Step1N2BubbleOn)
            {
                return !_device.RinseData.N2Valve;
            }
            else
            {
                return true;
            }
        }
        /// <summary>
        /// 启动N2和关闭Dump Valve
        /// </summary>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 检验Fill Valve打开状态
        /// </summary>
        /// <returns></returns>
        private bool CheckFillValveOn()
        {
            _startFillTime = DateTime.Now;
            _fillingDetectStartWaterLevel = _device.RinseData.WaterLevel;
            return true;
        }

        /// <summary>
        /// 检验是否正常注水
        /// </summary>
        /// <returns></returns>
        private bool CheckFillNormalStatus()
        {
            double currentWaterLevel = _device.RinseData.WaterLevel;
            return (currentWaterLevel - _fillingDetectStartWaterLevel) > _fillingStartedDelta;
        }

        /// <summary>
        /// 检验是否注满
        /// </summary>
        /// <returns></returns>
        private bool CheckFillFullStatus()
        {
            double currentWaterLevel = _device.RinseData.WaterLevel;
            bool result = currentWaterLevel > _sensorReadingFull;
            return result;
        }
        /// <summary>
        /// 增加已完成Rinses的次数
        /// </summary>
        /// <returns></returns>
        private bool CountNumberofRinsesComplete()
        {
            _rinseCycleTwo_RinsesCompleted++;
            return true;
        }
        /// <summary>
        /// 开始Dwell
        /// </summary>
        /// <returns></returns>
        private bool StartDwell()
        {
            bool 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 true;
        }
        /// <summary>
        /// 打开Dump Valve
        /// </summary>
        /// <returns></returns>
        private bool StartOpenDumpValve()
        {
            CheckNeedCloseMetalDrain();
            bool result = _device.DrainValveOn();
            if (!result)
            {
               NotifyError(eEvent.ERR_RINSE, "Open Dump valve error", 0);
                return false;
            }
            return result;
        }
        /// <summary>
        /// 检验快排是否排空
        /// </summary>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 检验是否需要关闭Metal Valve  加上第一步的number of rinse
        /// </summary>
        /// <returns></returns>
        private void CheckNeedCloseMetalDrain()
        {
            if (_recipe.Step1NumberOfRinse + _rinseCycleTwo_RinsesCompleted + 1 > _recipe.Step1NumberOfDumpToMetalDrain)
            {
                bool result = _device.WasteValveOn();
                if (!result)
                {
                   NotifyError(eEvent.ERR_RINSE, "Close Metal Drain Valve error", 0);
   
                }
            }
        }
        /// <summary>
        /// ResistivityStart
        /// </summary>
        /// <returns></returns>
        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;
        }
        /// <summary>
        /// ResistivityAveraging
        /// </summary>
        /// <returns></returns>
        private bool ResistivityAveraging()
        {
            if (_recipe.ResistivityDurationSeconds == 0)
            {
                _resistivitySample.Add(GetResitivity());
            }
            else
            {
                _startSampleTime = DateTime.Now;
                _sampeIntervalTime = DateTime.Now;
                _startSample = true;                
            }
            return true;
        }
        /// <summary>
        /// 采样Resitivity
        /// </summary>
        /// <returns></returns>
        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<ResistivityController>(_device.RinseItem.ResistivityID);
            if (resistivityController != null)
            {
                try
                {
                    resistivity = double.Parse(resistivityController.ResisitivityValue.Trim());
                }
                catch
                {
                    resistivity = 0;
                    //LOG.WriteLog(eEvent.ERR_RINSE, Module, "Resitivity value abnormal");
                }
            }
            return resistivity;
        }

        /// <summary>
        /// CheckResistivity
        /// </summary>
        /// <returns></returns>
        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);
            }
            _resistivitySample.Clear();
            return true;
        }

        private bool ResetRinseComplete()
        {
            _rinseCycleTwo_RinsesCompleted = 0;
            return true;
        }
  
        /// <summary>
        /// Abort
        /// </summary>
        public void Abort()
        {
            Runner.Stop("Manual abort");
        }


    }
}