using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Alarm;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.SubstrateTrackings;
using PunkHPX8_Core;
using PunkHPX8_RT.Devices.AXIS;
using PunkHPX8_RT.Devices.VpwCell;
using PunkHPX8_RT.Devices.VpwMain;
using PunkHPX8_RT.Modules.VpwMain;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PunkHPX8_RT.Modules.VpwCell
{
    public class VpwVacuumPrewetRoutine : RoutineBase, IRoutine
    {
        private enum PrepareStep
        {
            OpenVacuumValve,
            EnableVacuumPump,
            CheckVacuum,
            CloseVacuumValve,
            OpenVentValve,
            CheckLidReleaseVacuum,
            ChamberDown,
            CloseVentValve,
            ChamberUp,
            LastOpenVacuumValve,
            LastCheckVacuum,
            DryerHoldTime,
            OpenCellValve,
            LoopStart,
            LoopRun,
            LoopEnd,
            End
        }
        #region 内部变量
        /// 
        /// recipe
        /// 
        private VpwRecipe _recipe;
        /// 
        /// 设备
        /// 
        private VpwCellDevice _vpwCellDevice;
        /// 
        /// Main设备
        /// 
        private VpwMainDevice _mainDevice;
        /// 
        /// Pump DownWarn时间
        /// 
        private int _pumpDownWarningTime = 60000;
        /// 
        /// Pump Down超时
        /// 
        private int _pumpDownTimeOut = 80000;
        /// 
        /// 开始Pump Down时间
        /// 
        private DateTime _pumpDownTime=DateTime.MinValue;
        /// 
        /// 是否需要重试
        /// 
        private bool _isNeedRetry = false;
        /// 
        /// Lid Release Pressure
        /// 
        private int _lidReleasePressure = 730;
        /// 
        /// Lid Release Pressure 
        /// 
        private int _lidReleasePressureTimeout = 10000;
        /// 
        /// 总时长
        /// 
        private int _totalMicrosecond = 0;
        /// 
        /// 步骤
        /// 
        private int _stepIndex = 0;
        /// 
        /// 启动步骤时间
        /// 
        private DateTime _startStepTime = DateTime.Now;
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public VpwVacuumPrewetRoutine(string module) : base(module)
        {
        }
        /// 
        /// 中止
        /// 
        public void Abort()
        {
            Runner.Stop("Manual abort");
            _mainDevice.VPWBoostPumpTarget = VPWBoostPumpTarget.Pressure;
        }
        /// 
        /// 监控
        /// 
        /// 
        public RState Monitor()
        {
            Runner.Run(PrepareStep.OpenVacuumValve, PumpValveOn, _delay_1ms)
                .Run(PrepareStep.EnableVacuumPump, PumpEnable, _delay_1ms)
                .Wait(PrepareStep.CheckVacuum, CheckVacuumValue, _pumpDownTimeOut + 1000)
                .RunIf(PrepareStep.CloseVacuumValve, _isNeedRetry, PumpValveOff, _delay_1ms)
                .RunIf(PrepareStep.OpenVentValve, _isNeedRetry, OpenVentValve, _delay_1ms)
                .WaitIf(PrepareStep.CheckLidReleaseVacuum, _isNeedRetry, CheckLidReleaseVacuum, _lidReleasePressureTimeout*1000)
                .RunIf(PrepareStep.ChamberDown, _isNeedRetry, ChamberDown, CheckChamberOpened, _delay_10s)
                .RunIf(PrepareStep.CloseVentValve, _isNeedRetry, CloseVentValve, _delay_1ms)
                .RunIf(PrepareStep.ChamberUp, _isNeedRetry, ChamberUp, CheckChamberClosed, _delay_10s)
                .RunIf(PrepareStep.LastOpenVacuumValve, _isNeedRetry, PumpValveOn, _delay_1ms)
                .WaitIf(PrepareStep.LastCheckVacuum, _isNeedRetry,LastCheckVacuumValue, _pumpDownTimeOut)
                .Delay(PrepareStep.DryerHoldTime,_recipe.DryHoldTime*1000)
                .Run(PrepareStep.OpenCellValve,OpenCellValve,_delay_1ms)
                .LoopStart(PrepareStep.LoopStart,"Loop Step",_recipe.VacuumRinseStep.Count,NullFun,_delay_1ms)
                .LoopRunWithStopStatus(PrepareStep.LoopRun, CheckStepComplete, () => { return false; }, _totalMicrosecond + 60 * 1000)//总时长再延迟1分种
                .LoopEnd(PrepareStep.LoopEnd,NullFun,_delay_1ms)
                .End(PrepareStep.End,NullFun,_delay_1ms);
            return Runner.Status;
        }
        /// 
        /// pump valve on
        /// 
        /// 
        private bool PumpValveOn()
        {
            bool result = _vpwCellDevice.VacuumValveOn();
            if (!result)
            {
                NotifyError(eEvent.ERR_VPW, "pump valve on failed", 0);
            }
            return result;
        }
        /// 
        /// Pump valve off
        /// 
        /// 
        private bool PumpValveOff()
        {
            bool result = _vpwCellDevice.VacuumValveOff();
            if (!result)
            {
                NotifyError(eEvent.ERR_VPW, "pump valve off failed", 0);
            }
            return result;
        }
        /// 
        /// Pump Enable
        /// 
        /// 
        private bool PumpEnable()
        {
            bool result =_mainDevice.VacuumPumpEnable();
            if (!result)
            {
                NotifyError(eEvent.ERR_VPW, "pump enable failed", 0);
            }
            else
            {
                _pumpDownTime = DateTime.Now;
            }
            return result;
        }
        /// 
        /// 检验真空
        /// 
        /// 
        private bool CheckVacuumValue()
        {
            double vacuumValue = _vpwCellDevice.CommonData.VacuumPressure;
            if (vacuumValue <= _recipe.VacuumTarget)
            {
                return true;
            }
            if (DateTime.Now.Subtract(_pumpDownTime).TotalMilliseconds >= _pumpDownWarningTime)
            {
                //LOG.WriteLog(eEvent.WARN_VPW, Module, $"vacuum value {vacuumValue} is less than {_recipe.VacuumTarget} in PumpDownWarningTime");
                AlarmListManager.Instance.AddWarn(Module, "vacuum value", $"vacuum value {vacuumValue} is less than {_recipe.VacuumTarget} in PumpDownWarningTime\"" );
            }
            if (DateTime.Now.Subtract(_pumpDownTime).TotalMilliseconds >= _pumpDownTimeOut)
            {
                _isNeedRetry = true;
                LOG.WriteLog(eEvent.INFO_VPW, Module, $"Check Vacuum failed, Pump down retry start!");
                return true;
              
            }
            return false;
        }
        /// 
        /// 检验Lid Release真空数值
        /// 
        /// 
        private bool CheckLidReleaseVacuum()
        {
            double vacuumValue = _vpwCellDevice.CommonData.VacuumPressure;
            return vacuumValue >= _lidReleasePressure;
        }
        /// 
        /// open vent valve
        /// 
        /// 
        private bool OpenVentValve()
        {
            bool result = _vpwCellDevice.VentValveOn();
            if (!result)
            {
                NotifyError(eEvent.ERR_VPW, "open vent valve failed", 0);
            }
            return result;
        }
        /// 
        /// close vent valve
        /// 
        /// 
        private bool CloseVentValve()
        {
            bool result = _vpwCellDevice.VentValveOff();
            if (!result)
            {
                NotifyError(eEvent.ERR_VPW, "close vent valve failed", 0);
            }
            return result;
        }
        /// 
        /// Chamber down
        /// 
        /// 
        private bool ChamberDown()
        {
            bool result= _mainDevice.ChamberDown();
            if (!result)
            {
                NotifyError(eEvent.ERR_VPW, "chamber down failed",0);
            }
            return result;
        }
        /// 
        /// 检验Chamber是否打开 
        /// 
        /// 
        private bool CheckChamberOpened()
        {
            return _mainDevice.CommonData.ChamberOpened && !_mainDevice.CommonData.ChamberClosed;
        }
        /// 
        /// Chamber up
        /// 
        /// 
        private bool ChamberUp()
        {
            bool result = _mainDevice.ChamberUp();
            if (!result)
            {
                NotifyError(eEvent.ERR_VPW, "chamber up failed", 0);
            }
            return result;
        }
        /// 
        /// 检验Chamber是否关闭
        /// 
        /// 
        private bool CheckChamberClosed()
        {
            return !_mainDevice.CommonData.ChamberOpened && _mainDevice.CommonData.ChamberClosed;
        }
        /// 
        /// 检验真空
        /// 
        /// 
        private bool LastCheckVacuumValue()
        {
            double vacuumValue = _vpwCellDevice.CommonData.VacuumPressure;
            if (vacuumValue <= _recipe.VacuumTarget)
            {
                return true;
            }
            if (DateTime.Now.Subtract(_pumpDownTime).TotalMilliseconds >= _pumpDownWarningTime)
            {
                AlarmListManager.Instance.AddWarn(Module, "vacuum value", $"vacuum value {vacuumValue} is less than {_recipe.VacuumTarget}");
            }
            return false;
        }
        /// 
        /// 打开相应的cell valve
        /// 
        /// 
        private bool OpenCellValve()
        {
            int count = 0;
            int enableCount = 0;
            if (_recipe.VacuumPrewetDripEnable)
            {
                count += _vpwCellDevice.FlowDripOn()?1:0;
                enableCount++;
            }
            else
            {
                _vpwCellDevice.FlowDripOff();
            }
            if (_recipe.VacuumPrewetLargeEnable)
            {
                count += _vpwCellDevice.FlowLargeOn() ? 1 : 0;
                enableCount++;
            }
            else
            {
                _vpwCellDevice.FlowLargeOff();
            }
            if (_recipe.VacuumPrewetSmallEnable)
            {
                count += _vpwCellDevice.FlowSmallOn() ? 1 : 0;
                enableCount++;
            }
            else
            {
                _vpwCellDevice.FlowSmallOff();
            }
            bool result = count == enableCount;
            if (!result)
            {
                NotifyError(eEvent.ERR_VPW, "open cell valve failed", 0);
            }
            //boost pump
            _mainDevice.VPWBoostPumpTarget = VPWBoostPumpTarget.CellFlow;
            _mainDevice.BoostTargetFlow = _recipe.VacuumPrewetFlowSetPoint;
            _mainDevice.CommonData.BoosterPumpSpeedAuto = true;
            _mainDevice.CellFlow = _vpwCellDevice.CommonData.DiwFlow;
            if (!_mainDevice.BoosterPumpSpeed())
            {
                NotifyError(eEvent.ERR_VPW, "boost pump speed failed", 0);
                return false;
            }
            if (!_mainDevice.BoosterPumpEnableOperation("",null))
            {
                NotifyError(eEvent.ERR_VPW, "pump enable error",0);
                return false;
            }
            _mainDevice.CommonData.BoosterPumpStatusContent = "Auto:On";
            result = StartRotation();
            if (!result)
            {
                NotifyError(eEvent.ERR_VPW, "start rotation failed", 0);
                return false;
            }
            _startStepTime = DateTime.Now;
            _stepIndex = 0;
            return result;
        }
        /// 
        /// 同时旋转
        /// 
        /// 
        private bool StartRotation()
        {
            int targetPosition = 0;
            int maxSpeed = 0;
            int second = 0;
            foreach(var item in _recipe.VacuumRinseStep)
            {
                second += item.DurationSeconds;
                _totalMicrosecond += second * 1000;
                int speed = item.RotationSpeed;
                if (maxSpeed < speed)
                {
                    maxSpeed = speed;
                }
            }
            foreach(var item in _recipe.VentRinseStep)
            {
                second += item.DurationSeconds;
                int speed = item.RotationSpeed;
                if (maxSpeed < speed)
                {
                    maxSpeed = speed;
                }
            }
            foreach(var item in _recipe.ExtendCleanRinseStep)
            {
                second += item.DurationSeconds;
                int speed = item.RotationSpeed;
                if (maxSpeed < speed)
                {
                    maxSpeed = speed;
                }
            }
            second += _recipe.SpinTime;
            if (maxSpeed < _recipe.SpinSpeed)
            {
                maxSpeed= _recipe.SpinSpeed;
            }
            targetPosition = maxSpeed * (second + 60);//按最大速度*(时间+多出一分钟)
            _vpwCellDevice.SetRotationSpeed(_recipe.VacuumRinseStep[0].RotationSpeed * 6);
            return _vpwCellDevice.RotationProfilePosition(targetPosition);
        }
        /// 
        /// 检验步骤是否完成
        /// 
        /// 
        private bool CheckStepComplete()
        {
            _mainDevice.CellFlow = _vpwCellDevice.CommonData.DiwFlow;
            if (_stepIndex >= _recipe.VacuumRinseStep.Count)
            {
                LOG.WriteLog(eEvent.INFO_VPW, Module, $"vacuum step {_stepIndex} is over step count {_recipe.VacuumRinseStep.Count}");
                return true;
            }
            int length = _recipe.VacuumRinseStep[_stepIndex].DurationSeconds;
            if (DateTime.Now.Subtract(_startStepTime).TotalSeconds >= length)
            {
                _stepIndex++;
                _startStepTime = DateTime.Now;
                if (_stepIndex >= _recipe.VacuumRinseStep.Count)
                {
                    LOG.WriteLog(eEvent.INFO_VPW, Module, $"vaccum step {_stepIndex} is over step count {_recipe.VacuumRinseStep.Count}");
                    return true;
                }
                bool result = _vpwCellDevice.ChangeRotationSpeed(_recipe.VacuumRinseStep[_stepIndex].RotationSpeed*6);
                if (result)
                {
                    LOG.WriteLog(eEvent.INFO_VPW, Module, $"vacuum step {_stepIndex} complete");
                }
                return result;
            }
            int firstDelay = SC.GetValue($"{Module}.FlowCheckDelay") * 1000;
            if (DateTime.Now.Subtract(_startStepTime).TotalMilliseconds >= firstDelay)
            {
                bool abnormal = CheckDisable();
                if (abnormal)
                {
                    return false;
                }
            }
            return false;
        }
        /// 
        /// 检验数据
        /// 
        /// 
        private bool CheckDisable()
        {
            double flow = _vpwCellDevice.CommonData.DiwFlow;
            double lowError = _recipe.VacuumPrewetFlowSetPoint * (1 - (double)_recipe.VacuumPrewetFlowErrorPercent / 100);
            double upError = _recipe.VacuumPrewetFlowSetPoint * (1 + (double)_recipe.VacuumPrewetFlowErrorPercent / 100);
            double lowWarn = _recipe.VacuumPrewetFlowSetPoint * (1 - (double)_recipe.VacuumPrewetFlowWarningPercent / 100);
            double upWarn = _recipe.VacuumPrewetFlowSetPoint * (1 + (double)_recipe.VacuumPrewetFlowWarningPercent / 100);
            if (flow upError)
            {
                NotifyError(eEvent.ERR_VPW, $"{Module} cell flow {flow} is up than {upError} ", 0);
                Abort();
                return true;
            }
            if ((flow <= upError && flow >= upWarn) || (flow >= lowError && flow <= lowWarn))
            {
                string str = $"{Module} cell flow {flow} is in warning";
                if (AlarmListManager.Instance.AddWarn(Module, $"{Module} cell flow", str))
                {
                    LOG.WriteLog(eEvent.WARN_VPW, Module, str);
                }
            }
            bool isSimulatorMode = SC.GetValue("System.IsSimulatorMode");
            if (!isSimulatorMode)
            {
                if (!_vpwCellDevice.CheckRotationRunning())
                {
                    NotifyError(eEvent.ERR_VPW, $"{Module} rotation is stopped", 0);
                    Abort();
                    return true;
                }
            }
            return false;
        }
        /// 
        /// 启动
        /// 
        /// 
        /// 
        public RState Start(params object[] objs)
        {
            _recipe=(VpwRecipe)objs[0];
            _vpwCellDevice = DEVICE.GetDevice(Module);
            _mainDevice = DEVICE.GetDevice(ModuleName.VPWMain1.ToString());
            _pumpDownWarningTime = SC.GetValue($"{Module}.PumpDownWarningTime")*1000;
            _pumpDownTimeOut = SC.GetValue($"{Module}.PumpDownTimeout")*1000;
            _lidReleasePressure = SC.GetValue($"{Module}.LidReleasePressure");
            _lidReleasePressureTimeout = SC.GetValue($"{Module}.LidReleasePressureTimeout");
            _isNeedRetry = false;
            _totalMicrosecond = 0;
            _stepIndex = 0;
            return Runner.Start(Module, $"{Module} vacuum prewet");
        }
        /// 
        /// 重试
        /// 
        /// 
        public RState Retry(int step)
        {
            if (_recipe == null)
            {
                NotifyError(eEvent.ERR_VPW, "recipe is null", -1);
                return RState.Failed;
            }
            List preStepIds = new List();
            return Runner.Retry(PrepareStep.OpenVacuumValve, preStepIds, Module, "Vacuum Prewet Retry");
        }
    }
}