using Aitex.Core.Common;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using CyberX8_Core;
using CyberX8_RT.Devices.AXIS;
using CyberX8_RT.Devices.Facilities;
using CyberX8_RT.Devices.SRD;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.SubstrateTrackings;
namespace CyberX8_RT.Modules.SRD
{
    public class SRDUnloaderRoutine : RoutineBase, IRoutine
    {         
        private enum SRDUnloaderStep
        {
            Unload_FlippersOut,
            Unload_ChuckVacuumOff,
            Unload_ChuckATMOn,
            Unload_CheckVacuum,
            Unload_LiftUpOn,
            Unload_CheckWaferPresent,
            Unload_OpenDoor,
            End
        }
        #region 常量 
        private const int RETRY_TIMES = 3;
        #endregion
        #region 内部变量
        /// 
        /// Rotation Axis
        /// 
        private JetAxisBase _rotationAxis;
        /// 
        /// SRD Common
        /// 
        private SrdCommonDevice _srdCommon;
        /// 
        /// Total SRD
        /// 
        private TotalSRDDevice _totalSRDDevice;
        /// 
        /// System Facility
        /// 
        private SystemFacilities _systemFacilities;
        /// 
        /// 当前WaferSize
        /// 
        private int _waferSize = 200;
        /// 
        /// 当前Retry次数
        /// 
        private int _currentRetryTimes = 0;
        /// 
        /// 真空值
        /// 
        private int _vacuumOffLimit = 0;
        /// 
        /// Process Error状态
        /// 
        private bool _isProcessError = false;
        #endregion
        #region 属性
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public SRDUnloaderRoutine(string module) : base(module)
        {
        }
        /// 
        /// 中止
        /// 
        public void Abort()
        {
            Runner.Stop("SRD Loader Abort");
        }
        /// 
        /// 监控
        /// 
        /// 
        public RState Monitor()
        {
            Runner.RunIf(SRDUnloaderStep.Unload_FlippersOut, _isProcessError, FlippersOut, CheckFlippersOutEndStatus, CheckFlippersOutStopStatus)
                .Run(SRDUnloaderStep.Unload_ChuckVacuumOff, ChuckVacuumOff, CheckChuckVacuumOffEndStatus, CheckChuckVacuumOffStopStatus)
                .Run(SRDUnloaderStep.Unload_ChuckATMOn, ChuckATMOn, CheckChuckATMEndStatus, CheckChuckATMStopStatus)
                .WaitWithStopCondition(SRDUnloaderStep.Unload_CheckVacuum, CheckVacuumEndStatus, CheckVacuumStopStatus)
                .Run(SRDUnloaderStep.Unload_LiftUpOn, LiftUpOn, CheckLiftUpOnEndStatus, CheckLiftUpOnStopStatus)
                .Run(SRDUnloaderStep.Unload_CheckWaferPresent, CheckWaferPresent, _delay_1ms)
                .Run(SRDUnloaderStep.Unload_OpenDoor, OpenDoor, CheckDoorOpenedEndStatus, CheckDoorOpenedStopStatus)
                .End(SRDUnloaderStep.End, NullFun, _delay_1ms);
            return Runner.Status;
        }
        /// 
        /// 启动
        /// 
        /// 
        /// 
        public RState Start(params object[] objs)
        {
            _srdCommon = DEVICE.GetDevice($"{Module}.Common");
            _totalSRDDevice = DEVICE.GetDevice("SRD");
            _rotationAxis = DEVICE.GetDevice($"{Module}.Rotation");
            _systemFacilities = DEVICE.GetDevice("System.Facilities");
            _vacuumOffLimit = SC.GetValue("SRD.ChuckVacuumOffLimit");
            if (objs.Length >= 1)
            {
                _isProcessError = (bool)objs[0];
            } 
            if (!_isProcessError && !CheckPreCondition())
            {
                return RState.Failed;
            }
            if (!GetWaferSize())
            {
                NotifyError(eEvent.ERR_SRD, "Wafer Size is invalid", 0);
                return RState.Failed;
            }
            return Runner.Start(Module, "SRD Unloader Start");
        }
        /// 
        /// Check Pre Condition
        /// 
        /// 
        private bool CheckPreCondition()
        {
            //Check Rotation Home
            if (!_rotationAxis.IsHomed)
            {
                NotifyError(eEvent.ERR_SRD, "Rotation is not homed", 0);
                return false;
            }
            //Check LiftUp
            if (_srdCommon.CommonData.LiftUp)
            {
                NotifyError(eEvent.ERR_SRD, "LiftUp is on", 0);
                return false;
            }
            //Check LiftUp Status
            if (_srdCommon.CommonData.LiftUpStatus)
            {
                NotifyError(eEvent.ERR_SRD, "LiftUp sensor is on", 0);
                return false;
            }
            //Check Wafer Present
            if (!_srdCommon.CommonData.WaferPresent)
            {
                NotifyError(eEvent.ERR_SRD, "WaferPresent sensor is off", 0);
                return false;
            }
            //Check LoaderDI
            if (!_systemFacilities.LoaderDiEnable)
            {
                NotifyError(eEvent.ERR_SRD, "Load DI Is Disable", 0);
                return false;
            }
            //Check Vacuum
            int vacuumOnLimit = SC.GetValue("SRD.ChuckVacuumOnLimit");
            if (!_srdCommon.CommonData.ChuckVacuum)
            {
                if(_srdCommon.CommonData.VacuumValue >= vacuumOnLimit)
                {
                    LOG.WriteLog(eEvent.ERR_SRD, Module, $"VacuumValue:{_srdCommon.CommonData.VacuumValue}, VacuumOn Limit:{vacuumOnLimit}");
                    return false;
                }              
            }
            else
            {
                LOG.WriteLog(eEvent.ERR_SRD, Module, $"Chuck Vacuum is off");
                return false;
            }
            //Check Flippers
            if (_srdCommon.CommonData.FlippersIn150 || _srdCommon.CommonData.FlippersIn200) //|| _srdCommon.CommonData.FlippersIn100
            {
                NotifyError(eEvent.ERR_SRD, "FlippersIn is on", 0);
                return false;
            }
            if (!_srdCommon.CommonData.Flipper1Out150Status || !_srdCommon.CommonData.Flipper2Out150Status || !_srdCommon.CommonData.Flipper3Out150Status
                || !_srdCommon.CommonData.Flipper1Out200Status || !_srdCommon.CommonData.Flipper2Out200Status || !_srdCommon.CommonData.Flipper3Out200Status)
            //|| !_srdCommon.CommonData.Flipper1Out100Status || !_srdCommon.CommonData.Flipper2Out100Status || !_srdCommon.CommonData.Flipper3Out100Status
            {
                NotifyError(eEvent.ERR_SRD, "Flippers are at In position", 0);
                return false;
            }
            return true;
        }
        /// 
        /// ChuckATMOn
        /// 
        /// 
        private bool ChuckATMOn()
        {
            bool result = _srdCommon.ChuckATMAction("", null);
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD, "Chuck ATM Action is failed", 0);
                return result;
            }
            return true;
        }
        /// 
        /// Chuck ATM On End
        /// 
        /// 
        private bool CheckChuckATMEndStatus()
        {
            return _srdCommon.Status == RState.End && !_srdCommon.CommonData.ChuckATMOn;
        }
        /// 
        /// Chuck ATM On Stop
        /// 
        /// 
        private bool CheckChuckATMStopStatus()
        {
            if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
            {
                NotifyError(eEvent.ERR_SRD, "Check ChuckATM is failed", 0);
                return true;
            }
            return false;
        }
        /// 
        /// Check Vacuum End
        /// 
        /// 
        private bool CheckVacuumEndStatus()
        {
            if(_srdCommon.Status == RState.End && CheckVacuumValue())
            {
                return true;
            }          
            return false;
        }
        /// 
        /// Check Vacuum Stop
        /// 
        /// 
        private bool CheckVacuumStopStatus()
        {
            if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
            {
                NotifyError(eEvent.ERR_SRD, "Check ChuckATM is failed", 0);
                return true;
            }
            else if (_srdCommon.Status == RState.End)
            {
                if (_currentRetryTimes < RETRY_TIMES)
                {
                    _currentRetryTimes++;
                    NotifyError(eEvent.WARN_SRD, $"Current Chuck ATM Retry Times is {_currentRetryTimes}", 0);
                    _srdCommon.ChuckATMAction("", null);
                }
                else
                {
                    NotifyError(eEvent.ERR_SRD, $"Chuck ATM Retry Times is over {RETRY_TIMES}. ChuckATM is failed!", 0);
                    return true;
                }
            }
                    
            return false;
        }
        /// 
        /// Check Vacuum Value
        /// 
        /// 
        private bool CheckVacuumValue()
        {
            if (_srdCommon.CommonData.VacuumValue >= _vacuumOffLimit)
            {
                //LOG.WriteLog(eEvent.INFO_SRD, Module, $"VacuumValue:{_srdCommon.CommonData.VacuumValue}, VacuumOn Limit:{_vacuumOffLimit}");
                return true;
            }
            else
            {
                LOG.WriteLog(eEvent.WARN_SRD, Module, $"VacuumValue:{_srdCommon.CommonData.VacuumValue}, VacuumOn Limit:{_vacuumOffLimit}");
                return false;
            }
        }
        /// 
        /// LiftUpOff
        /// 
        /// 
        /// 
        private bool LiftUpOn()
        {
            bool result = _srdCommon.LiftUpOnAction("", null);
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD, "Lift Up On Action is failed", 0);
                return result;
            }
            return true;
        }
        /// 
        /// 检验LiftUpOff结束状态
        /// 
        /// 
        /// 
        private bool CheckLiftUpOnEndStatus()
        {
            return _srdCommon.Status == RState.End && _srdCommon.CommonData.LiftUpStatus;
        }
        /// 
        /// 检验LiftUpOff结束状态
        /// 
        /// 
        /// 
        private bool CheckLiftUpOnStopStatus()
        {
            if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
            {
                NotifyError(eEvent.ERR_SRD, "Check LiftUpOn is failed", 0);
                return true;
            }
            return false;
        }        
        /// 
        /// ChuckVacuumOn
        /// 
        /// 
        /// 
        private bool ChuckVacuumOff()
        {
            bool result = _srdCommon.ChuckVacuumOffAction("", null);
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD, "ChuckVacuumOff Action is failed", 0);
                return result;
            }
            return true;
        }
        /// 
        /// 检验ChuckVacuumOn结束状态
        /// 
        /// 
        /// 
        private bool CheckChuckVacuumOffEndStatus()
        {
            return _srdCommon.Status == RState.End && _srdCommon.CommonData.ChuckVacuum;
        }
        /// 
        /// 检验ChuckVacuumOn结束状态
        /// 
        /// 
        /// 
        private bool CheckChuckVacuumOffStopStatus()
        {
            if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
            {
                NotifyError(eEvent.ERR_SRD, "Check ChuckVacuumOff is failed", 0);
                return true;
            }
            return false;
        }
        /// 
        /// Check WaferPresent
        /// 
        /// 
        private bool CheckWaferPresent()
        {
            if (!_srdCommon.CommonData.WaferPresent)
            {
                NotifyError(eEvent.ERR_SRD, "WaferPresent sensor is off", 0);
                return false;
            }
            return true;
        }
        /// 
        /// Open Door
        /// 
        /// 
        /// 
        private bool OpenDoor()
        {
            return _srdCommon.DoorOpenAction("", null);
        }
        /// 
        /// 检验DoorOpened
        /// 
        /// 
        /// 
        private bool CheckDoorOpenedEndStatus()
        {
            bool result = _srdCommon.Status == RState.End;
            if (result)
            {
                if (_srdCommon.CommonData.DoorOpened && !_srdCommon.CommonData.DoorClosed)
                {
                    return true;
                }
                else
                {
                    NotifyError(eEvent.ERR_SRD, $"Opened {_srdCommon.CommonData.DoorOpened}&&Closed {_srdCommon.CommonData.DoorClosed}", 0);
                    return false;
                }
            }
            return false;
        }
        /// 
        /// 检验Door
        /// 
        /// 
        private bool CheckDoorOpenedStopStatus()
        {
            return _srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout;
        }
        /// 
        /// Flippers Out
        /// 
        /// 
        /// 
        private bool FlippersOut()
        {
            bool result = false;
            object[] objects = new object[1];
            objects[0] = _waferSize;
            result = _srdCommon.FlipperOutAction("", objects);
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD, $"FlipperOut{_waferSize} Action is failed", 0);
                return result;
            }
            return true;
        }
        /// 
        /// 检验FlippersOut结束状态
        /// 
        /// 
        /// 
        private bool CheckFlippersOutEndStatus()
        {
            return _srdCommon.Status == RState.End;
        }
        /// 
        /// 检验FlippersOut结束状态
        /// 
        /// 
        /// 
        private bool CheckFlippersOutStopStatus()
        {
            if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
            {
                NotifyError(eEvent.ERR_SRD, $"Check FlipperOut{_waferSize} Action is failed", 0);
                return true;
            }
            return false;
        }
        /// 
        /// Get current WaferSize
        /// 
        /// 
        private bool GetWaferSize()
        {
            WaferInfo waferInfo = WaferManager.Instance.GetWafer(ModuleNameString.ToEnum(Module), 0);
            if (waferInfo == null)
            {
                return false;
            }
            switch (waferInfo.Size)
            {
                case WaferSize.WS4:
                    _waferSize = 100;
                    break;
                case WaferSize.WS6:
                case WaferSize.WS150:
                case WaferSize.WS159:
                    _waferSize = 150;
                    break;
                case WaferSize.WS0:
                case WaferSize.WS8:
                    _waferSize = 200;
                    break;
                default:
                    return false;
            }
            return true;
        }
        /// 
        /// 关闭 Wafer N2
        /// 
        /// 
        private bool N2Off()
        {
            if(!_srdCommon.CommonData.N2On) return true;
            bool result = _srdCommon.N2OffAction("", null);
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD, $"N2 Off Action is failed", 0);
            }
            return result;
        }
        /// 
        /// Water Off
        /// 
        /// 
        /// 
        private bool WaterOff()
        {
            if (_srdCommon.CommonData.WaterOn)
            {
                bool result = _srdCommon.WaterOff();
                if (!result)               
                {
                    NotifyError(eEvent.ERR_SRD, "Water On is failed", 0);
                }
                return result;
            }
            return true;
        }
    }
}