using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Venus_RT.Devices;
using MECF.Framework.Common.Routine;
using Venus_Core;

namespace Venus_RT.Modules.PMs
{
    class LLPickRoutine : PMRoutineBase, IRoutine
    {
        private enum LLPickStep
        {
            kPrepareTransfer,
            kExtend,
            kPinUp,
            kRetract,
            kPostTransfer,
            kVentLoadLock,
        }

        private readonly LoadLockVentRoutine _loadLockVentRoutine;
        private int _prepareTransferTimeout = 120;
        private int _transferWaferTimeout = 120;
        private bool _isATMMode = false;
        public LLPickRoutine(JetPM chamber, LoadLockVentRoutine ventRoutine) : base(chamber)
        {
            Name = "PickWafer";
            _loadLockVentRoutine = ventRoutine;
        }

        public RState Start(params object[] objs)
        {
            _prepareTransferTimeout = SC.GetValue<int>($"{Module}.PrepareTransferTimeout");
            _transferWaferTimeout = SC.GetValue<int>($"{Module}.TransferWaferTimeout");
            _isATMMode = SC.GetValue<bool>("System.IsATMMode");

            if (_isATMMode)
            {
                if (!_chamber.IsATM || !_chamber.IsATMLoadlock)
                {
                    Stop("腔体非大气状态,请先执行充气动作");
                    return RState.Failed;
                }
            }
            else
            {
                if (!_chamber.IsVAC || !_chamber.IsVACLoadLock)
                {
                    Stop("腔体非真空状态,请先执行抽真空动作");
                    return RState.Failed;
                }
            }

            _chamber.OpenValve(ValveType.FastPump, false);
            _chamber.OpenValve(ValveType.LoadlockPumping, false);

            Reset();
            return Runner.Start(Module, Name);
        }
        public RState Monitor()
        {
            Runner.Run((int)LLPickStep.kPrepareTransfer,    PrepareTransfer,        IsPrepareReady,                                     _prepareTransferTimeout * 1000)
                .Run((int)LLPickStep.kExtend,               _chamber.ExtendWafer,   () => { return _chamber.IsLoadlockArmExtend; },     _transferWaferTimeout * 1000)
                .Run((int)LLPickStep.kPinUp,                SetLiftPinDown,         () => { return _chamber.CheckLiftDown(); })
                .Run((int)LLPickStep.kRetract,              _chamber.RetractWafer,  () => { return _chamber.IsLoadlockArmRetract; },    _transferWaferTimeout * 1000)
                .Run((int)LLPickStep.kPostTransfer,         PostTransfer,           IsPostTransferReady,                                _prepareTransferTimeout * 1000)
                .End((int)LLPickStep.kVentLoadLock,         VentLoadLock,           IsVentDone);

            return Runner.Status;
        }

        private bool PrepareTransfer()
        {
            _chamber.SetLiftPin(MovementPosition.Up, out _);
            _chamber.SetSlitDoor(true, out _);
            return true;
        }

        private bool IsPrepareReady()
        {
            return _chamber.CheckLiftUp() && _chamber.CheckSlitDoorOpen();
        }

        private bool PostTransfer()
        {
            _chamber.SetSlitDoor(false, out _);
            return true;
        }

        private bool IsPostTransferReady()
        {
            return _chamber.CheckLiftDown() && _chamber.CheckSlitDoorClose();
        }

        private bool SetLiftPinDown()
        {
            return _chamber.SetLiftPin(MovementPosition.Down, out _);
        }

        private bool VentLoadLock()
        {
            if (!_isATMMode)
            {
                return _loadLockVentRoutine.Start() == RState.Running;
            }
            else
                return true;
        }

        private bool IsVentDone()
        {
            RState ret = _loadLockVentRoutine.Monitor();
            if (ret == RState.Failed || ret == RState.Timeout)
            {
                Runner.Stop("Vent Failed");
                return false;
            }

            return ret == RState.End;
        }

        public void Abort()
        {
        }
    }
}