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.Equipment;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.Utilities;
using CyberX8_Core;
using CyberX8_RT.Devices.AXIS;
using CyberX8_RT.Devices.AXIS.CANOpen;
using CyberX8_RT.Modules.PUF;
using CyberX8_RT.Modules;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MECF.Framework.Common.CommonData.Loader;
using CyberX8_RT.Modules.Transporter;
using MECF.Framework.Common.WaferHolder;
using CyberX8_RT.Modules.Loader;
using Aitex.Core.Common;
namespace CyberX8_RT.Devices.Loader
{
    public class LoaderLoadRoutine : RoutineBase, IRoutine
    {
        private enum LoadStep
        {
            CheckPreCondition,
            WSClampOn,
            BernoulliN2On,
            BernoulliN2OnCheck,
            BernoulliBladderOff,
            BernoulliBladderOffCheck,
            TiltGotoFloat,
            TiltGotoFloatWait,
            Wait1,
            BernoulliBladderOn,
            BernoulliBladderOnCheck,
            CRSVacuumValue,
            CRSVacuumValueCheck,
            TiltGotoVertical,
            TiltGotoVerticalWait,
            CRSGotoUnlock,
            CRSGotoUnlockWait,
            WSBladderOn,
            WSBladderOnCheck,
            ShuttleGotoCRS,
            ShuttleGotoCRSWait,
            CRSGotoSetUp,
            CRSGotoSetUpWait,
            CRSGotoLock,
            CRSGotoLockWait,
            BernoulliN2Off,
            BernoulliN2OffCheck,
            WSBladderOff,
            WSBladderOffCheck,
            Wait2,
            CRSVacuumOff,
            CRSVacuumOffCheck,
            Wait3,
            ShuttleGotoMID,
            ShuttleGotoMIDWait,
            HomingCRSAxis,
            HomingCRSAxisWait,
            CRSHomedGotoSetUp,
            CRSHomedGotoSetUpCheck,
            End
 
        }
        #region 常量
        private const string SIDE_A = "SideA";
        private const string SIDE_B = "SideB";
        #endregion
        #region 内部变量
        private string _side = "";
        private int _crsVacuumReleaseDelayInMilliseconds = 250;
        private int _translateOutDelayInMilliseconds = 250;
        private int _waferSize = 200;
        private JetAxisBase _crsAxis;
        private JetAxisBase _tiltAxis;
        private JetAxisBase _shuttleAxis;
        private JetAxisBase _rotationAxis;
        private LoaderCommonDevice _loaderCommonDevice;
        private LoaderSideDevice _sideDevice;
        private LoaderSideBernoulliBladderRoutine _bernoulliBladderRoutine;
        private LoaderSideBernoulliN2PressureRoutine _bernoulliN2PressureRoutine;
        private LoaderSideVacuumAndLevelCheckRoutineRoutine _vacuumAndLevelCheckRoutineRoutine;
        private LoaderSideVacuumLevelCheckRoutine _vacuumLevelCheckRoutine;
        private LoaderSideWhBladderRoutine _whBladderRoutine;
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public LoaderLoadRoutine(string module,string side) : base(module)
        {
            _side = side;
        }
       
        /// 
        /// 中止
        /// 
        public void Abort()
        {
            Runner.Stop("Manual Abort");
        }
        /// 
        /// 监控
        /// 
        /// 
        public RState Monitor()
        {
            Runner.Run(LoadStep.CheckPreCondition, CheckPreCondition, _delay_1ms)
                //1 WSClamp On
                .Run(LoadStep.WSClampOn, WaferHolderClampOn, _delay_1ms)
                //2 BernoulliN2 On
                .Run(LoadStep.BernoulliN2On, () => { return _bernoulliN2PressureRoutine.Start(true) == RState.Running; }, _delay_1ms)
                .WaitWithStopCondition(LoadStep.BernoulliN2OnCheck, () => { return CommonFunction.CheckRoutineEndState(_bernoulliN2PressureRoutine); },
                    () => CheckRoutineStopStatus(_bernoulliN2PressureRoutine, "BernoulliN2 On failed"))
                //3 Bernoulli Bladder Off
                .Run(LoadStep.BernoulliBladderOff, () => { return _bernoulliBladderRoutine.Start(false) == RState.Running; }, _delay_1ms)
                .WaitWithStopCondition(LoadStep.BernoulliBladderOffCheck, () => { return CommonFunction.CheckRoutineEndState(_bernoulliBladderRoutine); },
                    () => CheckRoutineStopStatus(_bernoulliBladderRoutine, "BernoulliBladder Off failed"))
                //4 Tilt Goto Float
                .Run(LoadStep.TiltGotoFloat, () => { return AxisPosition(_tiltAxis, "FLOAT"); }, NullFun, _delay_1ms)
                .WaitWithStopCondition(LoadStep.TiltGotoFloatWait, () => { return _tiltAxis.Status == RState.End; },
                    () => CheckAxisMotionStopStatus(_tiltAxis))
                //5 等待0.5秒
                .Delay(LoadStep.Wait1, 500)
                //6 BernoulliBladder On
                .Run(LoadStep.BernoulliBladderOn, () => { return _bernoulliBladderRoutine.Start(true) == RState.Running; }, _delay_1ms)
                .WaitWithStopCondition(LoadStep.BernoulliBladderOnCheck, () => { return CommonFunction.CheckRoutineEndState(_bernoulliBladderRoutine); },
                    () => CheckRoutineStopStatus(_bernoulliBladderRoutine, "BernoulliBladder On failed"))
                //7 CRS Vacuum Check
                .Run(LoadStep.CRSVacuumValue, () => { return _vacuumLevelCheckRoutine.Start(true) == RState.Running; }, _delay_1ms)
                .WaitWithStopCondition(LoadStep.CRSVacuumValueCheck, () => { return CommonFunction.CheckRoutineEndState(_vacuumLevelCheckRoutine); },
                    () => CheckRoutineStopStatus(_vacuumLevelCheckRoutine, "CRS Vacuum Check failed"))
                //8 Tilt Goto Vertical
                .Run(LoadStep.TiltGotoVertical, () => { return AxisPosition(_tiltAxis, "VERT"); }, NullFun, _delay_1ms)
                .WaitWithStopCondition(LoadStep.TiltGotoVerticalWait, () => { return _tiltAxis.Status == RState.End; },
                    () => CheckAxisMotionStopStatus(_tiltAxis))
                //9 CRS Goto Unlock
                .Run(LoadStep.CRSGotoUnlock, () => { return AxisPosition(_crsAxis, $"Unlock{_waferSize}"); }, NullFun, _delay_1ms)
                .WaitWithStopCondition(LoadStep.CRSGotoUnlockWait, () => { return _crsAxis.Status == RState.End; },
                    () => CheckAxisMotionStopStatus(_crsAxis))
                //10 WS Bladder On
                .Run(LoadStep.WSBladderOn, () => { return _whBladderRoutine.Start(true) == RState.Running; }, _delay_1ms)
                .WaitWithStopCondition(LoadStep.WSBladderOnCheck, () => { return CommonFunction.CheckRoutineEndState(_whBladderRoutine); },
                    () => CheckRoutineStopStatus(_whBladderRoutine, "WSBladder On failed"))
                //11 Shuttle Goto CRS
                .Run(LoadStep.ShuttleGotoCRS, () => { return AxisPosition(_shuttleAxis, "LS"); }, NullFun, _delay_1ms)
                .WaitWithStopCondition(LoadStep.ShuttleGotoCRSWait, () => { return _shuttleAxis.Status == RState.End; },
                    () => CheckAxisMotionStopStatus(_shuttleAxis))
                //12 CRS Goto SetUp
                .Run(LoadStep.CRSGotoSetUp, () => { return AxisPosition(_crsAxis, $"Setup{_waferSize}"); }, NullFun, _delay_1ms)
                .WaitWithStopCondition(LoadStep.CRSGotoSetUpWait, () => { return _crsAxis.Status == RState.End; },
                    () => CheckAxisMotionStopStatus(_crsAxis))
                //13 CRS Goto Lock
                .Run(LoadStep.CRSGotoLock, () => { return AxisPosition(_crsAxis, $"Lock{_waferSize}"); }, NullFun, _delay_1ms)
                .WaitWithStopCondition(LoadStep.CRSGotoLockWait, () => { return _crsAxis.Status == RState.End; },
                    () => CheckAxisMotionStopStatus(_crsAxis))
                //.Run(LoadStep.CRSShortDistance, () => { return _crsAxis.ProfilePositionOperation(_crsAxis.MotionData.MotorPosition + _shortDistance); },_delay_1ms)
                //.WaitWithStopCondition(LoadStep.CRSShortDistanceWait, () => { return _crsAxis.Status == RState.End; },
                //    () => CheckAxisMotionStopStatus(_crsAxis))
                //14 Bernoulli N2 Off
                .Run(LoadStep.BernoulliN2Off, () => { return _bernoulliN2PressureRoutine.Start(false) == RState.Running; }, _delay_1ms)
                .WaitWithStopCondition(LoadStep.BernoulliN2OffCheck, () => { return CommonFunction.CheckRoutineEndState(_bernoulliN2PressureRoutine); },
                    () => CheckRoutineStopStatus(_bernoulliN2PressureRoutine, "Bernoulli N2 Off failed"))
                //15 WS Bladder Off
                .Run(LoadStep.WSBladderOff, () => { return _whBladderRoutine.Start(false) == RState.Running; }, _delay_1ms)
                .WaitWithStopCondition(LoadStep.WSBladderOffCheck, () => { return CommonFunction.CheckRoutineEndState(_whBladderRoutine); },
                    () => CheckRoutineStopStatus(_whBladderRoutine, "WS Bladder Off failed"))
                //16 等待0.5秒
                .Delay(LoadStep.Wait2, 500)
                //17 CRS Vacuum Off
                .Run(LoadStep.CRSVacuumOff, () => { return _vacuumAndLevelCheckRoutineRoutine.Start(false) == RState.Running; }, _delay_1ms)
                .WaitWithStopCondition(LoadStep.CRSVacuumOffCheck, () => { return CommonFunction.CheckRoutineEndState(_vacuumAndLevelCheckRoutineRoutine); },
                    () => CheckRoutineStopStatus(_vacuumAndLevelCheckRoutineRoutine, "LS Vacuum Off failed"))
                //18 等待0.5秒
                .Delay(LoadStep.Wait3, 500)
                //19 Shuttle Goto Mid
                .Run(LoadStep.ShuttleGotoMID, () => { return AxisPosition(_shuttleAxis, "MID"); }, NullFun, _delay_1ms)
                .WaitWithStopCondition(LoadStep.ShuttleGotoMIDWait, () => { return _shuttleAxis.Status == RState.End; },
                    () => CheckAxisMotionStopStatus(_shuttleAxis))
                //20 Home CRS Axis
                .Run(LoadStep.HomingCRSAxis, CRSHome, _delay_1ms)
                .WaitWithStopCondition(LoadStep.HomingCRSAxisWait, () => { return _crsAxis.Status == RState.End; },
                    () => CheckCRSHomeStopStatus())
                .Run(LoadStep.CRSHomedGotoSetUp, () => { return AxisPosition(_crsAxis, $"Setup{_waferSize}"); }, _delay_1ms)
                .WaitWithStopCondition(LoadStep.CRSHomedGotoSetUpCheck, () => { return _crsAxis.Status == RState.End; },
                    () => CheckAxisMotionStopStatus(_crsAxis))
                .End(LoadStep.End, UpdateWaferHolderLipCRSUsed);
            return Runner.Status; 
        }
        /// 
        /// 检验TranslateBladderOff异常状态
        /// 
        /// 
        private bool CheckRoutineStopStatus(IRoutine routine, string error)
        {
            bool result = CommonFunction.CheckRoutineStopState(routine);
            if (result)
            {
                NotifyError(eEvent.ERR_LOADER, $"{error}", 0);
            }
            return result;
        }
        /// 
        /// Axis goto position
        /// 
        /// 
        /// 
        /// 
        private bool AxisPosition(JetAxisBase axis, string station)
        {
            bool result = axis.PositionStation(station);
            if (!result)
            {
                NotifyError(eEvent.ERR_LOADER, $"{axis.Module} goto {station} failed", 0);
            }
            return result;
        }
        /// 
        /// 检验电机运动异常状态
        /// 
        /// 
        /// 
        private bool CheckAxisMotionStopStatus(JetAxisBase axis)
        {
            bool result = axis.Status == RState.Failed || axis.Status == RState.Timeout;
            if (result)
            {
                NotifyError(eEvent.ERR_LOADER, $"{axis.Module} motion failed", 0);
            }
            return result;
        }
        /// 
        /// CRS Home
        /// 
        /// 
        private bool CRSHome()
        {
            bool result = _crsAxis.Home();
            if (!result)
            {
                NotifyError(eEvent.ERR_LOADER, "LS Axis home failed", 0);
            }
            return result;
        }
        /// 
        /// 检验CRS home异常状态
        /// 
        /// 
        private bool CheckCRSHomeStopStatus()
        {
            bool result=_crsAxis.Status==RState.Failed||_crsAxis.Status==RState.Timeout;
            if (result)
            {
                NotifyError(eEvent.ERR_LOADER, "LS Axis home failed", 0);
            }
            return result;
        }
        /// 
        /// 启动
        /// 
        /// 
        /// 
        public RState Start(params object[] objs)
        {
            LoaderEntity loaderEntity = Singleton.Instance.GetModule(ModuleName.Loader1.ToString());
            if (_side == SIDE_A)
            {
                _waferSize = loaderEntity.SideAWaferSize;
            }
            else
            {
                _waferSize = loaderEntity.SideBWaferSize;
            }
            _crsAxis = GetCrsAxis();
            _tiltAxis = GetTiltAxis();
            _shuttleAxis= GetShuttleAxis();
            _loaderCommonDevice = DEVICE.GetDevice($"Loader1.Common");
            _rotationAxis = DEVICE.GetDevice($"{ModuleName.Loader1}.Rotation");
            _sideDevice = DEVICE.GetDevice($"{Module}.{_side}");
            _vacuumLevelCheckRoutine = new LoaderSideVacuumLevelCheckRoutine($"{Module}.{_side}");
            _whBladderRoutine = new LoaderSideWhBladderRoutine($"{Module}.{_side}");
            _bernoulliBladderRoutine = new LoaderSideBernoulliBladderRoutine($"{Module}.{_side}");
            _bernoulliN2PressureRoutine = new LoaderSideBernoulliN2PressureRoutine($"{Module}.{_side}");
            _vacuumAndLevelCheckRoutineRoutine = new LoaderSideVacuumAndLevelCheckRoutineRoutine($"{Module}.{_side}");
            if (SC.ContainsItem("Loader1.LSVacuumReleaseDelayInMilliseconds"))
            {
                _crsVacuumReleaseDelayInMilliseconds = SC.GetValue("Loader1.LSVacuumReleaseDelayInMilliseconds");
            }
            if (SC.ContainsItem("Loader1.TranslateOutDelayInMilliseconds"))
            {
                _translateOutDelayInMilliseconds = SC.GetValue("Loader1.TranslateOutDelayInMilliseconds");
            }
            Runner.Start(Module, "Load");
            return RState.Running;
        }
        /// 
        /// 获取Shuttle轴对象
        /// 
        /// 
        private JetAxisBase GetShuttleAxis()
        {
            switch (_side)
            {
                case "SideA":
                    return DEVICE.GetDevice($"{Module}.ShuttleA");
                default:
                    return DEVICE.GetDevice($"{Module}.ShuttleB");
            }
        }
        /// 
        /// 获取CRS轴对象
        /// 
        /// 
        private JetAxisBase GetCrsAxis()
        {
            switch(_side)
            {
                case "SideA":
                    return DEVICE.GetDevice($"{Module}.LSA");
                default:
                    return DEVICE.GetDevice($"{Module}.LSB");
            }
        }
        /// 
        /// 获取Tilt轴对象
        /// 
        /// 
        private JetAxisBase GetTiltAxis()
        {
            switch (_side)
            {
                case "SideA":
                    return DEVICE.GetDevice($"{Module}.TiltA");
                default:
                    return DEVICE.GetDevice($"{Module}.TiltB");
            }
        }
        /// 
        /// 检验前置条件
        /// 
        /// 
        private bool CheckPreCondition()
        {
            if(!CheckHomeCondition())
            {
                return false;
            }
            if(!CheckAxisCondition())
            {
                return false;
            }
            if(!StatusCheck())
            {
                return false;
            }
            if(!CRSVacuumCheck())
            {
                return false;
            }
            return true;
        }
        /// 
        /// 检验Home条件
        /// 
        /// 
        private bool CheckHomeCondition()
        {
            //检验PUF、Loader Transporter,Robot均Homed
            if (ModuleHelper.IsInstalled(ModuleName.PUF1))
            {
                PUFEntity puf1Entity = Singleton.Instance.GetModule(ModuleName.PUF1.ToString());
                if (!puf1Entity.IsHomed)
                {
                    NotifyError(eEvent.ERR_LOADER, "PUF1 is not homed",-1);
                    return false;
                }
            }
            if (ModuleHelper.IsInstalled(ModuleName.Loader1))
            {
                LoaderEntity loaderEntity = Singleton.Instance.GetModule(ModuleName.Loader1.ToString());
                if (!loaderEntity.IsHomed)
                {
                    NotifyError(eEvent.ERR_LOADER, "Loader is not homed", -1);
                    return false;
                }
            }
            if (ModuleHelper.IsInstalled(ModuleName.Transporter2))
            {
                TransporterEntity loaderTransportEntity = Singleton.Instance.GetModule(ModuleName.Transporter2.ToString());
                if (!loaderTransportEntity.IsHomed)
                {
                    NotifyError(eEvent.ERR_LOADER, "Loader Transporter is not homed",-1);
                    return false;
                }
            }
            return true;
        }
        /// 
        /// 检验Axis位置
        /// 
        /// 
        /// 
        private bool CheckAxisCondition()
        {
            if(!_rotationAxis.IsHomed)
            {
                NotifyError(eEvent.ERR_LOADER,  $"rotation is not homed",-1);
                return false;
            }
            if (!_shuttleAxis.IsHomed)
            {
                NotifyError(eEvent.ERR_LOADER,  $"{_shuttleAxis.Name} is not homed",-1);
                return false;
            }
            if (!_tiltAxis.IsHomed)
            {
                NotifyError(eEvent.ERR_LOADER,  $"{_tiltAxis.Name} is not homed", -1);
                return false;
            }
            if (!_crsAxis.IsHomed)
            {
                NotifyError(eEvent.ERR_LOADER,  $"{_crsAxis.Name} is not homed",-1);
                return false;
            }
            double rotationPosition = _rotationAxis.MotionData.MotorPosition; //校验rotation是否再load位置
            if (!_rotationAxis.CheckPositionIsInStation(rotationPosition, $"LOAD{_side.Substring(_side.Length- 1)}{_waferSize}"))
            {
                NotifyError(eEvent.ERR_LOADER,  $"rotation {rotationPosition} not in LOAD{_side.Substring(_side.Length - 1)}{_waferSize}", -1);
                return false;
            }
            double shuttlePosition=_shuttleAxis.MotionData.MotorPosition;//校验shuttle位置是否再out位置
            if (!_shuttleAxis.CheckPositionIsInStation(shuttlePosition, $"OUT{_waferSize}"))
            {
                NotifyError(eEvent.ERR_LOADER,  $"shuttle {shuttlePosition} not in OUT{_waferSize}",-1);
                return false;
            }
            double tiltPosition = _tiltAxis.MotionData.MotorPosition;//校验tilt是否在hori位置
            if (!_tiltAxis.CheckPositionIsInStation(tiltPosition, "HORI"))
            {
                NotifyError(eEvent.ERR_LOADER,  $"tilt {tiltPosition} not in HORI", -1);
                return false;
            }
            double crsPosition=_crsAxis.MotionData.MotorPosition;//校验crs是否在setup位置
            if (_crsAxis.CheckPositionIsInStation(tiltPosition, $"Setup{_waferSize}"))
            {
                NotifyError(eEvent.ERR_LOADER,  $"crs {crsPosition} not at Setup{_waferSize}",-1);
                return false;
            }
            return true;
        }
        /// 
        /// Wafer Holder Clamp On
        /// 
        /// 
        private bool WaferHolderClampOn()
        {
            bool result = _loaderCommonDevice.WaferHolderClampOnAction();
            if (!result)
            {
                NotifyError(eEvent.ERR_LOADER, "Wafer Shuttle Clamp on faied", 0);
            }
            return result;
        }
        /// 
        /// Status Check
        /// 
        /// 
        /// 
        private bool StatusCheck()
        {
            //判断是否放置wafershuttle
            if (!_loaderCommonDevice.CommonData.WaferHolderPresent)
            {
                NotifyError(eEvent.ERR_LOADER, "There is no wafer shuttle, can not do load", -1);
                return false;
            }
            return true;
        }
        /// 
        /// CRS Vacuum Check
        /// 
        /// 
        /// 
        private bool CRSVacuumCheck()
        {
            LoaderSideData sideData = _sideDevice.SideData;
            LoaderCommonData commonData = _loaderCommonDevice.CommonData;
            //Bernoulli Bladder
            if (!sideData.BernoulliBladder)
            {
                NotifyError(eEvent.ERR_LOADER, "BernoulliBladder is off", -1);
                return false;
            }
            if (sideData.BernoulliExtended)
            {
                NotifyError(eEvent.ERR_LOADER, "Bernoulli is Extended", -1);
                return false;
            }
            //Bernoulli N2
            if (sideData.BernoulliN2)
            {
                NotifyError(eEvent.ERR_LOADER, "Bernoulli N2 is On", -1);
                return false;
            }
            //CRS Vacuum检验
            if (!sideData.CRSVacuum)
            {
                NotifyError(eEvent.ERR_LOADER,  "LS Vacuum is off",-1);
                return false;
            }
            if (SC.ContainsItem($"{Module}.LSVacuumHighLimit"))  //真空值要大于最小设定值
            {
                double crsVacuumHighLimit = SC.GetValue($"{Module}.LSVacuumHighLimit");
                if (sideData.CRSVacuumValue >= crsVacuumHighLimit || sideData.CRSVacuumValue >= 0)
                {
                    NotifyError(eEvent.ERR_LOADER,  "LS Vacuum value is invalid", -1);
                    return false;
                }
            }
            //WS Clamp
            if (!commonData.WaferHolderClamp)
            {
                NotifyError(eEvent.ERR_LOADER, "Wafer Shuttle Clamp is off", -1);
                return false;
            }
            //WS Bladder
            if (sideData.WHBladder)
            {
                NotifyError(eEvent.ERR_LOADER, "WS Bladder is on", -1);
                return false;
            }
            //Drip Tray Fluid
            if (commonData.DripTrayFluid)
            {
                NotifyError(eEvent.ERR_LOADER, "Drip Tray Fluid is on", -1);
                return false;
            }
            //Wafer Shuttle Present
            if (!commonData.WaferHolderPresent)
            {
                NotifyError(eEvent.ERR_LOADER,  "Wafer Shuttle is absent",-1);
                return false;
            }
            return true;
        }
        /// 
        /// 更新WaferHolder LipCRS用量
        /// 
        /// 
        private bool UpdateWaferHolderLipCRSUsed()
        {
            WaferHolderInfo waferHolderInfo = WaferHolderManager.Instance.GetWaferHolder("Loader");
            if (waferHolderInfo != null)
            {
                if (!string.IsNullOrEmpty(waferHolderInfo.CrsAId)&&_side=="SideA")
                {
                    waferHolderInfo.CrsATotalUses++;
                    WaferHolderManager.Instance.UpdateWaferHolderInfo(waferHolderInfo);
                }
                if (!string.IsNullOrEmpty(waferHolderInfo.CrsBId) && _side == "SideB")
                {
                    waferHolderInfo.CrsBTotalUses++;
                    WaferHolderManager.Instance.UpdateWaferHolderInfo(waferHolderInfo);
                }
            }
            return true;
        }
    }
}