using Aitex.Core.RT.Device;
using Aitex.Core.RT.Routine;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Routine;
using CyberX8_Core;
using CyberX8_RT.Devices.AXIS;
using CyberX8_RT.Devices.Loader;
using System;
using System.Collections.Generic;
using Aitex.Core.RT.Log;
using MECF.Framework.Common.Utilities;
using MECF.Framework.Common.CommonData.Loader;
using MECF.Framework.Common.CommonData;
using Aitex.Core.RT.DataCenter;
namespace CyberX8_RT.Modules.Loader
{
    public class LoaderUnloadAllSideRoutine : RoutineBase, IRoutine
    {
        private enum UnloadStep
        {
            RotationGoToLOADA,
            RotationGoToLOADAWait,
            SideAUnload,
            Delay,
            SideBUnload,
            UnloadAllWait,
            End
        }
        #region 常量
        private const string SIDE_A = "SideA";
        private const string SIDE_B = "SideB";
        private const int LOTTRACK_TIME = 1000;
        #endregion
        #region 内部变量
        private JetAxisBase _rotationAxis;
        private LoaderUnloadRoutine _sideAUnloadRoutine;
        private LoaderUnloadRoutine _sideBUnloadRoutine;
        private bool _isSideAUnloaded = false;
        private bool _isSideBunloaded = false;
        private bool _isSideAStop = false;
        private bool _isSideBStop = false;
        /// 
        /// lotTrack time
        /// 
        private DateTime _lotTackTime = DateTime.Now;
        /// 
        /// Loader Common
        /// 
        private LoaderCommonDevice _loaderCommon;
        /// 
        /// LoaderSide A
        /// 
        private LoaderSideDevice _loaderSideA;
        /// 
        /// LoaderSide B
        /// 
        private LoaderSideDevice _loaderSideB;
        /// 
        /// Loader LotTrackData
        /// 
        private List _datas = new List();
        #endregion
        #region 属性
        /// 
        /// UnLoad LotTrackData
        /// 
        public List UnloadLotTrackDatas { get { return _datas; } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public LoaderUnloadAllSideRoutine(string module) : base(module)
        {
        }
        /// 
        /// 中止
        /// 
        public void Abort()
        {
        }
        /// 
        /// 监控
        /// 
        /// 
        public RState Monitor()
        {
            LottrackRecord();
            Runner.Run(UnloadStep.RotationGoToLOADA,RotationGotoLOADA,_delay_1ms)
                .WaitWithStopCondition(UnloadStep.RotationGoToLOADAWait,CheckRotationPositionStatus,CheckRotationPositionRunStop)
                .Run(UnloadStep.SideAUnload, () => StartUnloadRoutine(_sideAUnloadRoutine,_isSideAUnloaded), _delay_1ms)
                .Delay(UnloadStep.Delay,500)
                .Run(UnloadStep.SideBUnload, () => StartUnloadRoutine(_sideBUnloadRoutine,_isSideBunloaded), _delay_1ms)
                .WaitWithStopCondition(UnloadStep.UnloadAllWait, CheckUnloadAllRoutineEndStatus,CheckUnloadAllRoutineStopStatus)
                .End(UnloadStep.End, NullFun, _delay_1ms);
            return Runner.Status;
        }
        /// 
        /// Rotation Goto LOADA
        /// 
        /// 
        private bool RotationGotoLOADA()
        {
            bool result = _rotationAxis.PositionStation("LOADA", false);
            if (!result)
            {
                NotifyError(eEvent.ERR_LOADER, "rotation start goto LOADA failed", 0);
            }
            return result;
        }
        /// 
        /// 检验Rotation移动状态
        /// 
        /// 
        private bool CheckRotationPositionStatus()
        {
            return _rotationAxis.Status == RState.End;
        }
        /// 
        /// 检验Rotation是否还在运动
        /// 
        /// 
        private bool CheckRotationPositionRunStop()
        {
            bool result = _rotationAxis.Status == RState.Failed || _rotationAxis.Status == RState.Timeout ;
            if (result)
            {
                NotifyError(eEvent.ERR_LOADER, "rotation goto position failed",0);
            }
            return result;
        }
        /// 
        /// 启动Unload routine
        /// 
        /// 
        /// 
        private bool StartUnloadRoutine(LoaderUnloadRoutine unloadRoutine,bool isSideUnloaded)
        {
            if (isSideUnloaded)
            {
                return true;
            }
            bool result= unloadRoutine.Start()==RState.Running;
            if(!result)
            {
                NotifyError(eEvent.ERR_LOADER, unloadRoutine.ErrorMsg, 0);
            }
            return result;
        }
        /// 
        /// 检验UnloadAll完成状态
        /// 
        /// 
        private bool CheckUnloadAllRoutineEndStatus()
        {
            bool sideAResult = true;
            if (!_isSideAUnloaded)
            {
                sideAResult = CheckUnloadRoutineEndStatus(_sideAUnloadRoutine);
            }
            bool sideBResult = true;
            if (!_isSideBunloaded)
            {
                sideBResult = CheckUnloadRoutineEndStatus(_sideBUnloadRoutine);
            }
            return sideAResult && sideBResult;
        }
        /// 
        /// 检查UnloadAll停止状态
        /// 
        /// 
        private bool CheckUnloadAllRoutineStopStatus()
        {
            bool sideAComplete = false;
            if (!_isSideAUnloaded&&!_isSideAStop)
            {
                RState ret = _sideAUnloadRoutine.Monitor();
                _isSideAStop = ret == RState.Failed || ret == RState.Timeout;
                sideAComplete = (ret != RState.Running);
                if (_isSideAStop)
                {
                    NotifyError(eEvent.ERR_LOADER, $"unload A failed\r\n{_sideAUnloadRoutine.ErrorMsg}", 1);
                }
            }
            bool sideBComplete = false;
            if(!_isSideBunloaded&&!_isSideBStop)
            {
                RState ret = _sideBUnloadRoutine.Monitor();
                _isSideBStop = ret == RState.Failed || ret == RState.Timeout;
                sideBComplete = (ret != RState.Running);
                if (_isSideBunloaded)
                {
                    NotifyError(eEvent.ERR_LOADER, $"unload B failed\r\n{_sideBUnloadRoutine.ErrorMsg}", 1);
                }
            }
            return (_isSideAStop && sideBComplete) || (_isSideBStop && sideAComplete);
        }
        /// 
        /// 检验routine完成状态
        /// 
        /// 
        /// 
        private bool CheckUnloadRoutineEndStatus(LoaderUnloadRoutine unloadRoutine)
        {
            return unloadRoutine.Monitor() == RState.End;
        }
        /// 
        /// 检验Routine结束状态
        /// 
        /// 
        /// 
        private bool CheckUnloadRoutineStopStatus(LoaderUnloadRoutine unloadRoutine,string side) 
        {
            RState state=unloadRoutine.Monitor();
            if (state == RState.Failed || state == RState.Timeout)
            {
                NotifyError(eEvent.ERR_LOADER, $"{side} Unload failed", 0);
                return true;
            }
            return false;
        }
        /// 
        /// 启动
        /// 
        /// 
        /// 
        public RState Start(params object[] objs)
        {
            InitializeParameters();
            _loaderCommon = DEVICE.GetDevice($"{Module}.Common");
            _loaderSideA = DEVICE.GetDevice($"{Module}.SideA");
            _loaderSideB = DEVICE.GetDevice($"{Module}.SideB");
            return Runner.Start(Module, "Start UnloadAll");
        }
        /// 
        /// 初始化参数
        /// 
        private void InitializeParameters()
        {
            _rotationAxis = DEVICE.GetDevice($"{Module}.Rotation");
            _sideAUnloadRoutine = new LoaderUnloadRoutine(ModuleName.Loader1.ToString(), "SideA");
            _sideBUnloadRoutine = new LoaderUnloadRoutine(ModuleName.Loader1.ToString(), "SideB");
            _isSideAUnloaded = false;
            _isSideBunloaded = false;
            _isSideAStop = false;
            _isSideBStop = false;
        }
        /// 
        /// 重试
        /// 
        /// 
        public RState Retry(int step)
        {
            InitializeParameters();
            List preStepIds = new List();
            if (step == 0||step==-1)
            {
                return Runner.Retry(UnloadStep.RotationGoToLOADA,preStepIds,Module,"UnloadAll Retry");
            }
            else
            {
                _isSideAUnloaded = CheckSideUnloadCondition("A", step,false);
                _isSideBunloaded= CheckSideUnloadCondition("B", step,false);
                AddPreSteps(UnloadStep.SideAUnload, preStepIds);
                return Runner.Retry(UnloadStep.SideBUnload,preStepIds, Module, $"UnloadAll step {UnloadStep.SideBUnload} Retry");
            }
        }
        /// 
        /// 忽略前
        /// 
        /// 
        /// 
        private void AddPreSteps(UnloadStep step,List preStepIds)
        {
            for(int i = 0;i<(int)step;i++)
            {
                preStepIds.Add((UnloadStep)i);
            }
        }
        /// 
        /// 检验前面Unload完成状态
        /// 
        /// 
        public bool CheckCompleteCondition(int index)
        {
            if (!CheckSideUnloadCondition("A", index,true))
            {
                return false;
            }
            if (!CheckSideUnloadCondition("B", index, true))
            {
                return false;
            }
            return true;
        }
        /// 
        /// 检验Side Unload情况 
        /// 
        /// 
        /// 
        /// 
        private bool CheckSideUnloadCondition(string side, int index,bool showError)
        {
            JetAxisBase shuttleAxis = DEVICE.GetDevice($"{ModuleName.Loader1}.Shuttle{side}");
            double shuttlePosition = shuttleAxis.MotionData.MotorPosition;
            if (!shuttleAxis.CheckPositionIsInStation(shuttlePosition, "OPEN"))
            {
                if (showError)
                {
                    NotifyError(eEvent.ERR_LOADER, $"shuttle{side} {shuttlePosition} is not in open", index);
                }
                return false;
            }
            JetAxisBase tiltAxis = DEVICE.GetDevice($"{ModuleName.Loader1}.Tilt{side}");
            double tiltPosition = tiltAxis.MotionData.MotorPosition;
            if (!tiltAxis.CheckPositionIsInStation(tiltPosition, "HORI"))
            {
                if (showError)
                {
                    NotifyError(eEvent.ERR_LOADER, $"tilt{side} {tiltPosition} is not in HORI", index);
                    return false;
                }
            }
            JetAxisBase crsAxis = DEVICE.GetDevice($"{ModuleName.Loader1}.LS{side}");
            double crsPosition = crsAxis.MotionData.MotorPosition;
            if (!crsAxis.CheckPositionIsInStation(crsPosition, "Unlock"))
            {
                if (showError)
                {
                    NotifyError(eEvent.ERR_LOADER, $"LS{side} {crsPosition} is not in Unlock", index);
                }
                return false;
            }
            LoaderSideDevice loaderSideDevice = DEVICE.GetDevice($"{ModuleName.Loader1}.Side{side}");
            if (loaderSideDevice.SideData.DoorLowerLocked || loaderSideDevice.SideData.DoorUpperLocked)
            {
                if (showError)
                {
                    NotifyError(eEvent.ERR_LOADER, $"side{side} door locked", index);
                }
            }
            return true;
        }
        /// 
        /// 记录Lottrack
        /// 
        private void LottrackRecord()
        {
            //记录Lottrack
            if (DateTime.Now.Subtract(_lotTackTime).TotalMilliseconds >= LOTTRACK_TIME)
            {
                AddLotTrackData();
                _lotTackTime = DateTime.Now;
            }
        }
        /// 
        /// 获取Lot Track数据
        /// 
        /// 
        private void AddLotTrackData()
        {
            LoaderLotTrackData data = new LoaderLotTrackData();
            data.TimeStamp = DateTime.Now;
            data.LoaderABernoulliBladderEnable = _loaderSideA.SideData.BernoulliBladder;
            data.LoaderABernoulliExtended = _loaderSideA.SideData.BernoulliExtended;
            data.LoaderABernoulliBladderPressure = _loaderSideA.SideData.BernoulliBladderPressure;
            data.LoaderABernoulliN2Pressure = _loaderSideA.SideData.BernoulliPressure;
            data.LoaderACRSVacuum = _loaderSideA.SideData.CRSVacuum;
            data.LoaderACRSVacuumAnlg = _loaderSideA.SideData.CRSVacuumValue;
            data.LoaderAWHPressure = _loaderSideA.SideData.WHBladderPressure;
            data.LoaderATranslatePressure = _loaderSideA.SideData.TransPressure;
            data.LoaderBBernoulliBladderEnable = _loaderSideB.SideData.BernoulliBladder;
            data.LoaderBBernoulliExtended = _loaderSideB.SideData.BernoulliExtended;
            data.LoaderBBernoulliBladderPressure = _loaderSideB.SideData.BernoulliBladderPressure;
            data.LoaderBBernoulliN2Pressure = _loaderSideB.SideData.BernoulliPressure;
            data.LoaderBCRSVacuum = _loaderSideB.SideData.CRSVacuum;
            data.LoaderBCRSVacuumAnlg = _loaderSideB.SideData.CRSVacuumValue;
            data.LoaderBWHPressure = _loaderSideB.SideData.WHBladderPressure;
            data.LoaderBTranslatePressure = _loaderSideB.SideData.TransPressure;
            data.LoaderWHClamped = _loaderCommon.CommonData.WaferHolderClamp;
            _datas.Add(data);
        }
        
    }
}