using Aitex.Core.RT.Device;
using Aitex.Core.RT.Fsm;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using Aitex.Core.Utilities;
using MECF.Framework.Common.Beckhoff.AxisProvider;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.Utilities;
using CyberX8_Core;
using CyberX8_RT.Backends;
using CyberX8_RT.Devices.AXIS;
using CyberX8_RT.Devices.Facilities;
using CyberX8_RT.Devices.Loader;
using CyberX8_RT.Devices.SRD;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Threading;
using Aitex.Core.RT.Routine;
namespace CyberX8_RT.Modules.SRD
{
    /// 
    /// RunWafer状态机
    /// 
    public class RunWaferRecipeStateMachine : Entity, IEntity
    {
        #region 常量 
        private const int MAX_ARM_HOME_RETRIES = 3;
        /// 
        /// 旋转增加时长
        /// 
        private const int ROTATION_PLUS_TIME = 10;
        /// 
        /// ROTATION电机转速比例
        /// 
        private const int SPEED_RATIO = 10;
        #endregion
        #region 内部变量
        /// 
        /// 模块名称
        /// 
        private string _module;
        /// 
        /// Arm Axis
        /// 
        private JetAxisBase _armAxis;
        /// 
        /// Rotation Axis
        /// 
        private JetAxisBase _rotationAxis;
        /// 
        /// SRD Common
        /// 
        private SrdCommonDevice _srdCommon;
        /// 
        /// Total SRD
        /// 
        private TotalSRDDevice _totalSRDDevice;
        /// 
        /// 另外SRD实例 
        /// 
        private SRDEntity _otherSrdEntity;
        /// 
        /// Loader Common
        /// 
        private SystemFacilities _systemFacilities;
        /// 
        /// Arm是否Home
        /// 
        private bool _armIsHomed;
        /// 
        /// Arm重试次数
        /// 
        private int _armRetryTimes = 0;
        /// 
        /// ARM正在执行Home
        /// 
        private bool _armHoming = false;
        /// 
        /// 是否正在用水
        /// 
        private bool _isUsingWater = false;
        /// 
        /// Recipe
        /// 
        private SrdRecipe _srdRecipe;
        /// 
        /// 记时
        /// 
        private int _enterTime;
        /// 
        /// Diverting Flow时长
        /// 
        private int _divertingFlowCheckTimeSpan;
        /// 
        /// Pooling Flow时长
        /// 
        private int _poolingFlowCheckTimeSpan;
        /// 
        /// Washing Flow时长
        /// 
        private int _washingFlowCheckTimeSpan;
        /// 
        /// SRD rotation Provider对象
        /// 
        private BeckhoffProviderAxis _rotationProviderAxis;
        /// 
        /// SRD arm Provider对象
        /// 
        private BeckhoffProviderAxis _armProviderAxis;
        /// 
        /// 转换增加的时间
        /// 
        private int _rotationPlusSecond = ROTATION_PLUS_TIME;
        /// 
        /// N2 Enabled
        /// 
        private bool _n2Enabled = false;
        /// 
        /// Dry速度
        /// 
        private int _drySpeed;
        /// 
        /// exhaust进入时间
        /// 
        private int _exhaustFanTime;
        /// 
        /// 旋转停止时间
        /// 
        private int _rotationStopTime;
        /// 
        /// 是否执行Rotation Stop
        /// 
        private bool _isExecuteRotationStop;
        /// 
        /// Wafer Presence Accel/Decel比例 
        /// 
        private int _waferPresenceCheckAccelDecelPercentage;
        /// 
        /// Wafer Presence Speed
        /// 
        private int _waferPresenceSpeedInRPMs;
        /// 
        /// Wafer Presence distance
        /// 
        private int _waferPresenceDistance;
        /// 
        /// 状态机进入时间
        /// 
        private int _startTime;
        /// 
        /// Wafer Presence Test功能是否启用
        /// 
        private bool _presenceTestEnabled;
        /// 
        /// PresenceTest记录次数
        /// 
        private int _presenceTestCount;
        /// 
        /// 当前次数
        /// 
        private int _currentCount;
        /// 
        /// Rinse时间=Max(FrontRinseTime, BackRinseTime) 单位s
        /// 
        private double _rinseTime;
        /// 
        /// Rinse中另一个水阀开关状态
        /// 
        private bool _isAnotherWaterOn;
        /// 
        /// PresenceTest是否完成
        /// 
        private bool _isTestComplete = true;
        /// 
        /// Rotation是否执行Position
        /// 
        private bool _isRotationExecutePosition = false;
        /// 
        /// PresenceTest进入时间
        /// 
        private int _presenceTestEnterTime;
        #endregion
        #region 属性
        /// 
        /// 状态
        /// 
        public string State { get { return ((RunWaferState)fsm.State).ToString(); } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public RunWaferRecipeStateMachine(string module) 
        {
            _module = module;
            this.fsm = new StateMachine($"{module}_RunWaferStateMachine", (int)RunWaferState.RunWafer_Complete, 10);
            fsm.EnableRepeatedMsg(true);           
            AnyStateTransition(RunWaferMsg.Init, EnterRunWaferStart, RunWaferState.RunWafer_Start);
            AnyStateTransition(RunWaferMsg.Error, EnterError, RunWaferState.Error);
            Transition(RunWaferState.RunWafer_Start, RunWaferMsg.RunWafer_Start, RunWaferStartCheckStatus, RunWaferState.RunWafer_CheckFacilities);
            Transition(RunWaferState.RunWafer_CheckFacilities, FSM_MSG.TIMER, CheckFacilities, RunWaferState.RunWafer_PreparingExhaustOff);
            Transition(RunWaferState.RunWafer_PreparingExhaustOff, FSM_MSG.TIMER, PreparingExhaustOff, RunWaferState.RunWafer_WaitExhaustOff);
            Transition(RunWaferState.RunWafer_WaitExhaustOff, FSM_MSG.TIMER, WaitExhaustOff, RunWaferState.RunWafer_EngageChuckVacuum);
            Transition(RunWaferState.RunWafer_EngageChuckVacuum, FSM_MSG.TIMER, EngageChuckVacuum, RunWaferState.RunWafer_CheckVacuum);
            Transition(RunWaferState.RunWafer_CheckVacuum, FSM_MSG.TIMER, CheckVacuum, RunWaferState.RunWafer_CloseTheDoor);
            Transition(RunWaferState.RunWafer_CloseTheDoor, FSM_MSG.TIMER,CloseDoor,RunWaferState.RunWafer_CheckDoorClosed);
            Transition(RunWaferState.RunWafer_CheckDoorClosed, FSM_MSG.TIMER, CheckDoorClosed, RunWaferState.RunWafer_ArmToHome);
            Transition(RunWaferState.RunWafer_ArmToHome, FSM_MSG.TIMER,ArmToHome, RunWaferState.RunWafer_Diverting_CheckArmHome);
            Transition(RunWaferState.RunWafer_Diverting_CheckArmHome, FSM_MSG.TIMER, CheckArmHome, RunWaferState.RunWafer_Diverting_CheckOtherSRD);
            Transition(RunWaferState.RunWafer_Diverting_CheckOtherSRD, FSM_MSG.TIMER, CheckOtherSRD, RunWaferState.RunWafer_Diverting_WaterOn);
            Transition(RunWaferState.RunWafer_Diverting_WaterOn, FSM_MSG.TIMER, WaterOn, RunWaferState.RunWafer_Diverting_WithFlowCheck);
            Transition(RunWaferState.RunWafer_Diverting_WithFlowCheck, FSM_MSG.TIMER, CheckFlow, RunWaferState.RunWafer_Washing_ArmToCenter);
            Transition(RunWaferState.RunWafer_Washing_ArmToCenter, FSM_MSG.TIMER, ArmToCenter, RunWaferState.RunWafer_Washing_CheckArmCenter);
            Transition(RunWaferState.RunWafer_Washing_CheckArmCenter, FSM_MSG.TIMER, CheckArmToCenter, RunWaferState.RunWafer_Washing_PoolingFrontSide);
            Transition(RunWaferState.RunWafer_Washing_PoolingFrontSide, FSM_MSG.TIMER, PoolingFrontSideWaterOn, RunWaferState.RunWafer_Washing_PoolingWithFlowCheck);
            Transition(RunWaferState.RunWafer_Washing_PoolingWithFlowCheck, FSM_MSG.TIMER, PoolingCheckFlow, RunWaferState.RunWafer_Washing_StartRotation);
            Transition(RunWaferState.RunWafer_Washing_StartRotation, FSM_MSG.TIMER, StartRotation, RunWaferState.RunWafer_Washing_PreFlowCheck);
            Transition(RunWaferState.RunWafer_Washing_PreFlowCheck, FSM_MSG.TIMER, WashingPreFlowCheck, RunWaferState.RunWafer_Washing_Finished);
            Transition(RunWaferState.RunWafer_Washing_Finished, FSM_MSG.TIMER, WashingFinished, RunWaferState.RunWafer_Drying_PreN2Time);
            Transition(RunWaferState.RunWafer_Drying_PreN2Time, FSM_MSG.TIMER, CheckArmMotion, RunWaferState.RunWafer_Drying_ExhaustFanDelay);
            Transition(RunWaferState.RunWafer_Drying_ExhaustFanDelay, FSM_MSG.TIMER, ExhaustFanDelay, RunWaferState.RunWafer_Drying_N2On);
            Transition(RunWaferState.RunWafer_Drying_N2On, FSM_MSG.TIMER, N2On, RunWaferState.RunWafer_Drying_PreWaferPresenceCheck);
            Transition(RunWaferState.RunWafer_Drying_PreWaferPresenceCheck, FSM_MSG.TIMER, PreWaferPresenceCheck, RunWaferState.RunWafer_Drying_WaferPresenceCheck);
            Transition(RunWaferState.RunWafer_Drying_WaferPresenceCheck, FSM_MSG.TIMER, WaferPresenceCheck, RunWaferState.RunWafer_Drying_PostN2Time);
            Transition(RunWaferState.RunWafer_Drying_PostN2Time, FSM_MSG.TIMER, PostN2Time, RunWaferState.RunWafer_Drying_CheckRotationFinished);
            Transition(RunWaferState.RunWafer_Drying_CheckRotationFinished, FSM_MSG.TIMER, CheckRotationFinished, RunWaferState.RunWafer_CheckArmHome);
            Transition(RunWaferState.RunWafer_CheckArmHome, FSM_MSG.TIMER, LastCheckArmHomed, RunWaferState.RunWafer_Complete);
            //PresenceTest
            Transition(RunWaferState.RunWafer_Complete, RunWaferMsg.PreWaferPresenceCheck, RunWaferStartCheckStatus, RunWaferState.RunWafer_Drying_PreWaferPresenceCheck);
            EnumLoop.ForEach((item) => { fsm.MapState((int)item, item.ToString()); });
            EnumLoop.ForEach((item) => { fsm.MapMessage((int)item, item.ToString()); });
        }
        private bool EnterError(object param)
        {
            
            //关闭风扇
            if (_srdCommon.CommonData.ExhaustOn)
            {
                bool result = _srdCommon.ExhaustOffAction("", null);
                if (!result)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "EnterError: Exhaust Off is failed");
                }
            }
            //关闭WaterAbove
            if (_srdCommon.CommonData.WaterAbove)
            {
                bool result = _srdCommon.WaterAboveOff();
                if (!result)
                {
                    LOG.WriteLog(eEvent.INFO_SRD, _module, "EnterError: Water Above Off is failed");
                }
            }
            //关闭WaterBelow
            if (_srdCommon.CommonData.WaterBelow)
            {
                bool result = _srdCommon.WaterBelowOff();
                if (!result)
                {
                    LOG.WriteLog(eEvent.INFO_SRD, _module, "EnterError: Water Below Off is failed");
                }
            }
            return true;
        }
        private bool EnterRunWaferStart(object param)
        {
            _isRotationExecutePosition = false;
            return true;
        }       
        #region 状态方法
        /// 
        /// 启动
        /// 
        /// 
        /// 
        private bool RunWaferStartCheckStatus(object param)
        {
            
            _startTime = Environment.TickCount;
            if(param!=null)
            {
                object[] parameters= (object[])param;
                _srdRecipe=(SrdRecipe)parameters[0];
            }
            if(_srdRecipe==null)
            {
                PostMsg(RunWaferMsg.Error);
                LOG.WriteLog(eEvent.ERR_SRD, _module, "srd recipe is null");
                return false;
            }
            _armAxis = DEVICE.GetDevice($"{_module}.Arm");
            if(!_armAxis.IsHomed)
            {
                PostMsg(RunWaferMsg.Error);
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Arm is not homed");
                return false;
            }
            _rotationAxis = DEVICE.GetDevice($"{_module}.Rotation");
            if (!_rotationAxis.IsHomed)
            {
                PostMsg(RunWaferMsg.Error);
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Rotation is not homed");
                return false;
            }
            _srdCommon = DEVICE.GetDevice($"{_module}.Common");
            _totalSRDDevice = DEVICE.GetDevice("SRD");
            if (_srdCommon.IsWaferPresence)
            {
                if (_srdCommon.WaferPresence != "WellPlaced")
                {
                    PostMsg(RunWaferMsg.Error);
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Wafer Presence is not WellPlaced");
                    return false;
                }
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_SRD, _module, "Wafer Presence Test has been ignored");
            }
                                
            if(SC.ContainsItem("SRD.SRDRotationPlusSecond"))
            {
                _rotationPlusSecond = SC.GetValue("SRD.SRDRotationPlusSecond");
            }
            if(SC.ContainsItem("SRD.N2Enabled"))
            {
                _n2Enabled = SC.GetValue("SRD.N2Enabled");
            }
            //Wafer Presence Test
            if (SC.ContainsItem($"SRD.{_module}EnablePresenceCheckvalue"))
            {
                _presenceTestEnabled = SC.GetValue($"SRD.{_module}EnablePresenceCheckvalue");
            }
            _systemFacilities = DEVICE.GetDevice("System.Facilities");
            string otherSRD = _module == "SRD1" ? "SRD2" : "SRD1";
            _otherSrdEntity = Singleton.Instance.GetModule(otherSRD);
            _rotationProviderAxis = BeckhoffAxisProviderManager.Instance.GetAxisProvider($"{_module}.Rotation");
            if (_rotationProviderAxis == null)
            {
                PostMsg(RunWaferMsg.Error);
                LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.Rotation Provider is not exist");
                return false;
            }
            _armProviderAxis = BeckhoffAxisProviderManager.Instance.GetAxisProvider($"{_module}.Arm");
            if (_armProviderAxis == null)
            {
                PostMsg(RunWaferMsg.Error);
                LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.Arm Provider is not exist");
                return false;
            }
            _waferPresenceCheckAccelDecelPercentage = SC.GetValue("SRD.WaferPresenceCheckAccelDecelPercentage");
            _waferPresenceSpeedInRPMs = SC.GetValue("SRD.WaferPresenceCheckSpeedInRPMs");
            _waferPresenceDistance = SC.GetValue("SRD.WaferPresenceCheckDistanceInDegrees");
            return true;
        }
        /// 
        /// 检查Facilities
        /// 
        /// 
        /// 
        private bool CheckFacilities(object param)
        {
            if (_srdCommon.CommonData.FluidContainment)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Fluid Containment sensor is On"); 
                PostMsg(RunWaferMsg.Error);
                return false;
            }
            if(!_systemFacilities.LoaderDiEnable)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Load DI Is Disable");
                PostMsg(RunWaferMsg.Error);
                return false;
            }
            return true;
        }
        /// 
        /// 关闭Exhaust风机
        /// 
        /// 
        /// 
        private bool PreparingExhaustOff(object param)
        {
            bool result = _srdCommon.ExhaustOffAction("", null);
            if (!result)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Preparing Exhaust Off is failed");
                PostMsg(RunWaferMsg.Error);
                return false;
            }                 
            return true;
        }
        /// 
        /// 等待Exhaust风机关闭状态
        /// 
        /// 
        /// 
        private bool WaitExhaustOff(object param)
        {
            if (_srdCommon.Status==RState.Failed||_srdCommon.Status==RState.Timeout)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Waiting Exhaust Off is failed");
                PostMsg(RunWaferMsg.Error);
                return false;
            }
            return _srdCommon.Status == RState.End && !_srdCommon.CommonData.ExhaustOn;
        }
        /// 
        /// Chuck Vacuum
        /// 
        /// 
        /// 
        private bool EngageChuckVacuum(object param)
        {
            if (_srdCommon.IsWaferPresence)
            {
                bool result = _srdCommon.ChuckVacuumOnAction("", null);
                if (!result)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Chuck Vacuum On Action is failed");
                    PostMsg(RunWaferMsg.Error);
                }
                return result;
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_SRD, _module, "EngageChuckVacuum has been ignored");
                return true;
            }
                        
        }
        /// 
        /// 检查真空状态
        /// 
        /// 
        /// 
        private bool CheckVacuum(object param)
        {
            if (_srdCommon.IsWaferPresence)
            {
                if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Check Vacuum is failed");
                    PostMsg(RunWaferMsg.Error);
                    return false;
                }
                return _srdCommon.Status == RState.End && !_srdCommon.CommonData.ChuckVacuum;
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_SRD, _module, "CheckVacuum has been ignored");
                return true;
            }
            
        }
        /// 
        /// Close Door
        /// 
        /// 
        /// 
        private bool CloseDoor(object param)
        {
            if (_srdCommon.CommonData.DoorOpened)
            {
                bool result = _srdCommon.DoorCloseAction("", null);
                if (!result)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Door Close Action is failed");
                    PostMsg(RunWaferMsg.Error);
                    return result;
                }
            }           
            return true;
        }
        /// 
        /// 检验DoorClosed
        /// 
        /// 
        /// 
        private bool CheckDoorClosed(object param)
        {
            if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Check Door Closed is failed");
                PostMsg(RunWaferMsg.Error);
                return false;
            }
            return _srdCommon.Status == RState.End && _srdCommon.CommonData.DoorClosed;
        }
        /// 
        /// Arm To Home
        /// 
        /// 
        private bool ArmToHome(object param)
        {
            if (!_armHoming)
            {
                _armAxis.Home(false);
                _armHoming = true;
                return false;
            }
            else
            {
                if(_armAxis.Status != RState.End)
                {
                    return false;
                }
            }
            _armHoming = false;
            _armIsHomed = _armAxis.IsHomed;
            return true;
        }
        /// 
        /// 检验ARM,发现失败,则重试
        /// 
        /// 
        /// 
        private bool CheckArmHome(object param)
        {
            if (_armIsHomed)
            {
                return true;
            }
            else
            {
                if(_armRetryTimes
        /// 检验另外一个SRD是否在用水
        /// 
        /// 
        /// 
        private bool CheckOtherSRD(object param)
        {
            if (_otherSrdEntity == null)
            {
                return true;
            }
            return !_otherSrdEntity.IsUsingWater;
        }
        /// 
        /// 打开Above water
        /// 
        /// 
        /// 
        private bool WaterOn(object param)
        {
            if (_srdRecipe.FrontDivertTime>0)
            {
                if(_srdRecipe.FrontDivertTime>_srdRecipe.DivertPlusPoolDelay)
                {
                    _divertingFlowCheckTimeSpan = _srdRecipe.DivertPlusPoolDelay * 1000;
                }
                else
                {
                    _divertingFlowCheckTimeSpan = _srdRecipe.FrontDivertTime*1000;
                }
                if (!_srdCommon.CommonData.WaterAbove)
                {
                    bool result = _srdCommon.WaterAboveOn();
                    if (result)
                    {
                        LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above On");
                        _isUsingWater = true;
                        _enterTime = Environment.TickCount;
                    }
                    else
                    {
                        LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above On is failed");
                        PostMsg(RunWaferMsg.Error);
                    }
                    return result;
                }                 
                return false;
            }
            else
            {
                return true;
            }
        }
        /// 
        /// 检验水压
        /// 
        /// 
        /// 
        private bool CheckFlow(object param)
        {
            if (_srdRecipe.FrontDivertTime==0)
            {
                return true;
            }
            else
            {
                int ticks = Environment.TickCount - _enterTime;
                if(ticks<=_divertingFlowCheckTimeSpan)
                {
                    if(_totalSRDDevice.WaterPressure>_srdRecipe.MaxDivertPlusPoolPressure)
                    {
                        LOG.WriteLog(eEvent.ERR_SRD, _module,$"Water Pressure {_totalSRDDevice} is over {_srdRecipe.MaxDivertPlusPoolPressure}");
                        PostMsg(RunWaferMsg.Error);
                        return false;
                    }
                }
                else
                {
                    if (ticks >= _srdRecipe.FrontDivertTime*1000)
                    {
                        if (_srdCommon.CommonData.WaterAbove)
                        {
                            bool result = _srdCommon.WaterAboveOff();
                                               
                            if (result)
                            {
                                LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above off");
                            }
                            else
                            {
                                LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above On is failed");
                                PostMsg(RunWaferMsg.Error);
                            }
                            return result;
                        }                      
                    }
                }
            }
            return false;
        }
        /// 
        /// Arm运动至Center
        /// 
        /// 
        /// 
        private bool ArmToCenter(object param)
        {
            bool result= _armAxis.PositionStation("Center");
            if(!result)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Arm to Center is failed");
                PostMsg(RunWaferMsg.Error);
            }
            return result;
        }
        /// 
        /// check Arm是否运动至Center
        /// 
        /// 
        /// 
        private bool CheckArmToCenter(object param)
        {
            if (_armAxis.Status==RState.End)
            {
                return true;
            }
            else if(_armAxis.Status==RState.Failed)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Check Arm to Center is failed");
                PostMsg(RunWaferMsg.Error);
                return false;
            }
            return false;
        }
        /// 
        /// 打开Above water
        /// 
        /// 
        /// 
        private bool PoolingFrontSideWaterOn(object param)
        {
            if (_srdRecipe.FrontPoolTime > 0)
            {
                if (_srdRecipe.FrontPoolTime > _srdRecipe.DivertPlusPoolDelay)
                {
                    _poolingFlowCheckTimeSpan = _srdRecipe.DivertPlusPoolDelay * 1000;
                }
                else
                {
                    _poolingFlowCheckTimeSpan = _srdRecipe.FrontDivertTime * 1000;
                }
                if (!_srdCommon.CommonData.WaterAbove)
                {
                    bool result = _srdCommon.WaterAboveOn();
                    if (result)
                    {
                        LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above On");
                        _enterTime = Environment.TickCount;
                        if (_isUsingWater)
                        {
                            _isUsingWater = true;
                        }
                    }
                    else
                    {
                        LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above On is failed");
                        PostMsg((int)RunWaferMsg.Error);
                    }
                    return result;
                }
                return true;
            }
            else
            {
                return true;
            }
        }
        /// 
        /// 检验水压
        /// 
        /// 
        /// 
        private bool PoolingCheckFlow(object param)
        {
            if (_srdRecipe.FrontPoolTime == 0)
            {
                return true;
            }
            else
            {
                int ticks = Environment.TickCount - _enterTime;
                if (ticks <= _poolingFlowCheckTimeSpan)
                {
                    if (_totalSRDDevice.WaterPressure > _srdRecipe.MaxWashPressure)
                    {
                        LOG.WriteLog(eEvent.ERR_SRD, _module, $"Water Pressure {_totalSRDDevice.WaterPressure} is over {_srdRecipe.MaxWashPressure}");
                        PostMsg((int)RunWaferMsg.Error);
                        return false;
                    }
                    if (_totalSRDDevice.WaterPressure < _srdRecipe.MinWaterPressure)
                    {
                        LOG.WriteLog(eEvent.ERR_SRD, _module, $"Water Pressure {_totalSRDDevice.WaterPressure} is less {_srdRecipe.MinWaterPressure}");
                        PostMsg((int)RunWaferMsg.Error);
                        return false;
                    }
                }
                else
                {
                    if (ticks >= _srdRecipe.FrontPoolTime * 1000)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        /// 
        /// 开始旋转
        /// 
        /// 
        /// 
        private bool StartRotation(object param)
        {
            if (_srdCommon.CommonData.DoorOpened)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Door is not closed. Can't do rotation");
                PostMsg(RunWaferMsg.Error);
                return false;
            }
            double _scale = _rotationProviderAxis.ScaleFactor;
            bool above = _srdRecipe.FrontRinseTime > _srdRecipe.BackRinseTime;
            int timespan = above ? _srdRecipe.FrontRinseTime : _srdRecipe.BackRinseTime;
            //rinse 目标位置 
            double rinsePosition = timespan * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.RinseSpeed);
            //dry目标位置
            double dryPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.DrySpeed) * _srdRecipe.BackN2DryTime;
            //为了让 rotation 不停止,增加了旋转时间(覆盖Arm运动时间)
            double plusPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.DrySpeed) * _rotationPlusSecond;
            int targetPosition = (int)Math.Round((rinsePosition + dryPosition + plusPosition) * _scale, 0);
            int rotationSpeed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.RinseSpeed),0);
            _drySpeed= (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.DrySpeed * SPEED_RATIO), 0);
            bool result= _rotationAxis.ProfilePosition(targetPosition, rotationSpeed * SPEED_RATIO, 0, 0);
            if(!result)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Start Rotation is failed");
                PostMsg(RunWaferMsg.Error);
                return false;
            }
            LOG.WriteLog(eEvent.INFO_SRD, _module, "Start Rotation");
            //如果BackRinseTime大,则先开WaterBelow后开WaterAbove        
            if (_srdRecipe.BackRinseTime>_srdRecipe.FrontRinseTime)
            {
                _rinseTime = _srdRecipe.BackRinseTime;
                //关闭WaterAbove
                if (_srdCommon.CommonData.WaterAbove)
                {                    
                    if (!_srdCommon.WaterAboveOff())
                    {
                        LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above Off is failed");
                        PostMsg((int)RunWaferMsg.Error);
                        return false;
                    }
                    LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above Off");
                }
                //打开WaterBelow
                if (!_srdCommon.CommonData.WaterBelow)
                {
                    if (!_srdCommon.WaterBelowOn())
                    {
                        LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Below On is failed");
                        PostMsg((int)RunWaferMsg.Error);
                        return false;
                    }
                    LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Below On");
                } 
                //Rinse开始时间
                _enterTime = Environment.TickCount;
                //另一个水阀状态变为未开(即WaterAbove)
                _isAnotherWaterOn = false;
                //计算水压检测滞后时间
                if (_srdRecipe.BackRinseTime > _srdRecipe.FlowCheckDelay)
                {
                    _washingFlowCheckTimeSpan = _srdRecipe.FlowCheckDelay * 1000;
                }
                else
                {
                    _washingFlowCheckTimeSpan = _srdRecipe.BackRinseTime * 1000;
                }
                
                return true;
            }
            else
            {
                _rinseTime = _srdRecipe.FrontRinseTime;
                //如果FrontRinseTime大,则先开WaterAbove后开WaterBelow
                //打开WaterAbove
                if (!_srdCommon.CommonData.WaterAbove)
                {
                    if (!_srdCommon.WaterAboveOn())
                    {
                        LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above Off is failed");
                        PostMsg((int)RunWaferMsg.Error);
                        return false;
                    }
                    LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above On");
                }
                //关闭WaterBelow
                if (_srdCommon.CommonData.WaterBelow)
                {
                    //打开WaterBelow
                    if (!_srdCommon.WaterBelowOff())
                    {
                        LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Below On is failed");
                        PostMsg((int)RunWaferMsg.Error);
                        return false;
                    }
                    LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Below Off");
                }
                //另一个水阀状态变为未开(即WaterBelow)
                _isAnotherWaterOn = false;
                //Rinse开始时间
                _enterTime = Environment.TickCount;
                //计算水压检测滞后时间
                if (_srdRecipe.FrontRinseTime > _srdRecipe.FlowCheckDelay)
                {
                    _washingFlowCheckTimeSpan = _srdRecipe.FlowCheckDelay * 1000;
                }
                else
                {
                    _washingFlowCheckTimeSpan = _srdRecipe.BackRinseTime * 1000;
                }
                return true;
            }
        }
        /// 
        /// 检验水压
        /// 
        /// 
        /// 
        private bool WashingPreFlowCheck(object param)
        {
            int ticks = Environment.TickCount - _enterTime;
            //打开另一个未开的水阀
            if(!_isAnotherWaterOn)
            {
                //延迟abs(BackRinseTime - FrontRinseTime)秒打开另一个水阀
                if (_srdRecipe.BackRinseTime > _srdRecipe.FrontRinseTime)
                {
                    //若BackRinseTime > FrontRinseTime,则延迟BackRinseTime - FrontRinseTime秒打开Water Above
                    if (ticks >= _rinseTime*1000 - _srdRecipe.FrontRinseTime*1000 && !_srdCommon.CommonData.WaterAbove)
                    {
                        bool result = _srdCommon.WaterAboveOn();
                        if (!result)
                        {
                            LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above Off is failed");
                            PostMsg((int)RunWaferMsg.Error);
                            return false;
                        }
                        _isAnotherWaterOn = true;
                        LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above On");
                    }
                }
                else
                {
                    //若FrontRinseTime > BackRinseTime,则延迟FrontRinseTime - BackRinseTime秒打开Water Below
                    if (ticks >= _rinseTime * 1000 - _srdRecipe.BackRinseTime * 1000 && !_srdCommon.CommonData.WaterBelow)
                    {
                        bool result = _srdCommon.WaterBelowOn();
                        if (!result)
                        {
                            LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Below On is failed");
                            PostMsg((int)RunWaferMsg.Error);
                            return false;
                        }
                        LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Below On");
                    }
                }
            }
                    
            if (ticks >= _rinseTime * 1000)
            {
                //达到RinseTime完成Wash
                return true;
            }
            else if (ticks > _washingFlowCheckTimeSpan)
            {
                if (_totalSRDDevice.WaterPressure > _srdRecipe.MaxWashPressure)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, $"Water Pressure {_totalSRDDevice.WaterPressure} is over {_srdRecipe.MaxWashPressure}");
                    PostMsg((int)RunWaferMsg.Error);
                    return false;
                }
                if (_totalSRDDevice.WaterPressure < _srdRecipe.MinWaterPressure)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, $"Water Pressure {_totalSRDDevice.WaterPressure} is less {_srdRecipe.MinWaterPressure}");
                    PostMsg((int)RunWaferMsg.Error);
                    return false;
                }
            }
            else
            {
                return false;
            }
            return false;
        }
        /// 
        /// Washing结束
        /// 
        /// 
        /// 
        private bool WashingFinished(object param)
        {
            if (_srdCommon.CommonData.WaterAbove)
            {
                if(!_srdCommon.WaterAboveOff())
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above Off is failed");
                    PostMsg(RunWaferMsg.Error);
                    return false;
                }
            }
            if(_srdCommon.CommonData.WaterBelow)
            {
                if(!_srdCommon.WaterBelowOff())
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Below Off is failed");
                    PostMsg(RunWaferMsg.Error);
                    return false;
                }
            }
            _isUsingWater = false;
            if(_n2Enabled)
            {
                bool result= _armAxis.PositionStation("Center");
                if(!result)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Arm to Center is failed");
                    PostMsg(RunWaferMsg.Error);
                }
                return result;
            }
            else
            {
                bool result= _armAxis.PositionStation("Home");
                if (!result)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Arm To Home is failed");
                    PostMsg(RunWaferMsg.Error);
                }
                return result;
            }
        }
        /// 
        /// 检验Arm是否运动到位
        /// 
        /// 
        private bool CheckArmMotion(object param)
        {
            //Arm是否运动到位
            if (_armAxis.Status==RState.End)
            {
                //调整速度为 drySpeed
                bool result= _rotationAxis.ChangeSpeed(_drySpeed);
                if(!result)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Change Speed to Dry Speed is failed");
                    return false;
                }
                if(_n2Enabled)
                {
                    //todo 打开N2 Above和N2 Below
                }
                _exhaustFanTime = Environment.TickCount;
                return true;
            }
            else if(_armAxis.Status==RState.Failed)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, "Arm Axis Status is in Failed");
                PostMsg(RunWaferMsg.Error);
                return false;
            }
            return false;
        }
        /// 
        /// Exhaust delay
        /// 
        /// 
        /// 
        private bool ExhaustFanDelay(object param)
        {
            int ticks = Environment.TickCount - _exhaustFanTime;
            if (ticks >= _srdRecipe.ExhaustFanDelay * 1000)
            {
                bool result = _srdCommon.ExhaustOn();
                if(!result)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Exhaust On failed");
                    PostMsg(RunWaferMsg.Error);
                    return false;
                }
                _enterTime = Environment.TickCount;
                return true;
            }
            return false;
        }
        /// 
        /// N2 On
        /// 
        /// 
        /// 
        private bool N2On(object param)
        {
            if (_n2Enabled)
            {
                //todo 关闭N2Above和N2 Below
            }
            
            int ticks = Environment.TickCount - _enterTime;
            if(ticks > _srdRecipe.BackN2DryTime * 1000) return true;
            return false;
        }
        /// 
        /// Pre WaferPresence Check
        /// 
        /// 
        private bool PreWaferPresenceCheck(object param)
        {
            if (!_isExecuteRotationStop)
            { 
                //停止Rotation
                bool result= _rotationAxis.StopPositionOperation();
                LOG.WriteLog(eEvent.INFO_SRD, _module, "Stop Rotation is done");
                _rotationStopTime = Environment.TickCount;
                _isExecuteRotationStop = true;
                if(!result)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Stop Rotation is failed");
                    PostMsg(RunWaferMsg.Error);
                }
            }
            else
            {
                int ticks=Environment.TickCount-_rotationStopTime;
                if(ticks>=5*1000)//固定时间5秒,确认Rotation是否已经停下
                {
                    if(!_rotationAxis.IsRun && _rotationAxis.Status == RState.End)
                    {
                        _isExecuteRotationStop = false;
                        return true;
                    }
                    else
                    {
                        LOG.WriteLog(eEvent.ERR_SRD, _module, "SRD Rotation Stop time span is over 5 seconds");
                        PostMsg(RunWaferMsg.Error);
                        return false;
                    }
                }
            }
            return false;
        }
        /// 
        /// Wafer Presence Check
        /// 
        /// 
        /// 
        private bool WaferPresenceCheck(object param)
        {
            double scale = _rotationProviderAxis.ScaleFactor;
            int currentRotation = (int)Math.Round(_rotationAxis.MotionData.MotorPosition * scale, 0);
            //Presence Test目标位置(单位为°)
            int targetPosition = (int)Math.Round(scale * _waferPresenceDistance,0)+currentRotation;
            //转速单位转换 RPM(r/min) to degree/s
            double degree = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_waferPresenceSpeedInRPMs);
            //Presence Test目标转速
            int profileVelocity =(int)Math.Round(scale*degree,0);
            //加速度
            int acceleration = (int)Math.Round(_rotationAxis.ProfileAcceleration * _waferPresenceCheckAccelDecelPercentage / 100, 0);
            //减速度
            int deceleration = (int)Math.Round(_rotationAxis.ProfileDeceleration * _waferPresenceCheckAccelDecelPercentage / 100, 0);
            if (!_isRotationExecutePosition)
            {
                if (_srdCommon.CommonData.DoorOpened)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Door is not closed. Can't do rotation");
                    PostMsg(RunWaferMsg.Error);
                    return false;
                }
                bool result = _rotationAxis.ProfilePosition(targetPosition, profileVelocity * SPEED_RATIO, acceleration, deceleration);
                if (!result)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Start Rotation is failed");
                    PostMsg(RunWaferMsg.Error);
                }
                _isRotationExecutePosition = true;
                if (_srdCommon.IsWaferPresence && _presenceTestEnabled)
                {
                    //PresenceTest记录次数=(目标位置/目标转速)*1000ms /500ms
                    _presenceTestCount = (int)Math.Floor(_waferPresenceDistance / degree * 1000 / 500);
                    LOG.WriteLog(eEvent.INFO_SRD, _module, $"Presence Test Count is about {_presenceTestCount} times");
                    //当前test次数归零
                    _currentCount = 0;
                    //开始计时
                    _presenceTestEnterTime = Environment.TickCount;
                    _isTestComplete = false;
                    LOG.WriteLog(eEvent.INFO_SRD, _module, "Presence Test Timer is started");
                }
                return false;
            }
            else
            {
                //PresenceTestEnable开启则进行测试
                if (!_isTestComplete && _srdCommon.IsWaferPresence && _presenceTestEnabled)
                {
                    int ticks = Environment.TickCount - _presenceTestEnterTime;
                    //500ms检测一次
                    if(ticks >= 500)
                    {
                        if (_srdCommon.WaferPresence == "WellPlaced")
                        {
                            _currentCount++;
                            LOG.WriteLog(eEvent.INFO_SRD, _module, $"The {_currentCount}th Presence Test is successful");
                            //更新PresenceTestEnterTime
                            _presenceTestEnterTime = Environment.TickCount;
                            if(_currentCount >= _presenceTestCount)
                            {
                                //PresenceTest通过                        
                                _isTestComplete = true;
                                LOG.WriteLog(eEvent.INFO_SRD, _module, $"The Presence Test of {_module} is all successful");
                            }
                            else
                            {
                                return false;
                            }
                        }
                        else
                        {
                            LOG.WriteLog(eEvent.ERR_SRD, _module, $"The {_currentCount + 1}th Presence Test is failed");
                            LOG.WriteLog(eEvent.ERR_SRD, _module, $"The Presence Test of {_module} is failed");
                            PostMsg(RunWaferMsg.Error);
                            return false;
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
                
                if (_rotationAxis.Status!=RState.End)
                {
                    return false;
                }
            }
           
            return true;
        }
        /// 
        /// Post N2 Time(Stop rotation ,home rotation)
        /// 
        /// 
        /// 
        private bool PostN2Time(object param)
        {           
            bool homeResult = _rotationAxis.Home(false);
            if(!homeResult)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.Arm is not homed");
                PostMsg(RunWaferMsg.Error);
                return false;
            }
            return true;
        }
        /// 
        /// 检验Rotation是否Homed
        /// 
        /// 
        /// 
        private bool CheckRotationFinished(object param)
        {
            //关闭排风扇
            if (_srdCommon.CommonData.ExhaustOn && _srdCommon.Status != RState.Running)
            {
                bool result1 = _srdCommon.ExhaustOffAction("", null);
                if (!result1)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Preparing Exhaust Off is failed");
                    PostMsg(RunWaferMsg.Error);
                }
            }
            
            bool result= _rotationAxis.IsHomed && _rotationAxis.Status == RState.End;
            if(_rotationAxis.Status!=RState.Running)
            {
                if(!_rotationAxis.IsHomed)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.rotation is not homed");
                }
                return true;
            }
            return false;
        }
        /// 
        /// 检验
        /// 
        /// 
        /// 
        private bool LastCheckArmHomed(object param)
        {
            string currentLocation = _armAxis.CurrentStation;
            bool armHomed= _armAxis.IsHomed;
            if(!armHomed)
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.Arm is not homed");
                PostMsg(RunWaferMsg.Error);
                return false;
            }
            if (!currentLocation.Contains("Home"))
            {
                LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.Arm is not in home station");
                PostMsg(RunWaferMsg.Error);
                return false;
            }
            LOG.WriteLog(eEvent.INFO_SRD, _module, $"Run Wafer State Machine 状态 {RunWaferState.RunWafer_Start}==>{RunWaferState.RunWafer_Complete} Total Time[{Environment.TickCount - _startTime}]");
            return true;
        }
        #endregion
        /// 
        /// 停止 
        /// 
        public void Stop()
        {           
            base.Terminate();
        }
        public bool Check(int msg, out string reason, params object[] args)
        {
            reason = "";
            return false;
        }
        #region State Msg枚举
        public enum RunWaferState
        {
            None,
            Error,
            RunWafer_Start,
            RunWafer_CheckFacilities,
            RunWafer_PreparingExhaustOff,
            RunWafer_WaitExhaustOff,
            RunWafer_EngageChuckVacuum,
            RunWafer_CheckVacuum,
            RunWafer_CloseTheDoor,
            RunWafer_CheckDoorClosed,
            RunWafer_ArmToHome,
            RunWafer_Diverting_CheckArmHome,
            RunWafer_Diverting_CheckOtherSRD,
            RunWafer_Diverting_WaterOn,
            RunWafer_Diverting_WithFlowCheck,
            RunWafer_Washing_ArmToCenter,
            RunWafer_Washing_CheckArmCenter,
            RunWafer_Washing_PoolingFrontSide,
            RunWafer_Washing_PoolingWithFlowCheck,
            RunWafer_Washing_StartRotation,
            RunWafer_Washing_PreFlowCheck,
            RunWafer_Washing_Finished,
            RunWafer_Drying_PreN2Time,
            RunWafer_Drying_ExhaustFanDelay,
            RunWafer_Drying_N2On,
            RunWafer_Drying_PreWaferPresenceCheck,
            RunWafer_Drying_WaferPresenceCheck,
            RunWafer_Drying_PostN2Time,
            RunWafer_Drying_CheckRotationFinished,
            RunWafer_CheckArmHome,
            RunWafer_Complete
        }
        public enum RunWaferMsg
        {
            Init,
            Error,
            RunWafer_Start,
            CheckFacilities,
            PreparingExhaustOff,
            WaitExhaustOff,
            EngageChuckVacuum,
            CloseTheDoor,
            ArmToHome,
            CheckOtherSRD,
            DivertingWaterAboveOn,
            ArmToCenter,
            PoolingFrontWaterAboveOn,
            StartRotation,
            Washing_Finished,
            N2On,
            PreWaferPresenceCheck,
            WaferPresenceCheck,
            PostN2Time,
            CheckArmHome,
            Abort
        }
        #endregion
    }
}