using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Sorter.Common;
using CyberX8_RT.Devices;
using MECF.Framework.Common.Jobs;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.SubstrateTrackings;
using CyberX8_Core;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using MECF.Framework.Common.Schedulers;
using System.Collections.Generic;
using CyberX8_RT.Devices.EFEM;

namespace CyberX8_RT.Modules.EFEM
{
    class EfemSwapRoutine : ModuleRoutineBase, IRoutine
    {
        private enum SwapStep
        {
            WaitModuleReady,
            ModulePrepare,
            OpenSlitDoor,
            MoveWafer,
            WaitMaferMoved,
            CloseSlitDoor,
            NotifyDone,
        }

        private readonly EfemBase _efem;

        private int _moveTimeout = 20 * 1000;


        Queue<MoveItem> _actionList = new Queue<MoveItem>();
        MoveItem _currentAction;
        private int _actionCount = 0;

        private int _autoPumpOptInWafer = 4;
        private int _autoPumpOptOutWafer = 0;

        private bool _bAutoMode = true;

        public EfemSwapRoutine(EfemBase efem) : base(ModuleName.EfemRobot)
        {
            _efem = efem;

            Name = "Swap";
        }
        public RState Start(params object[] objs)
        {
            if (!_efem.IsHomed)
            {
                LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, Module, $"EFEM is not homed, please home it first");
                return RState.Failed;
            }

            _actionList.Clear();
            foreach (var item in (Queue<MoveItem>)objs[0])
            {
                _actionList.Enqueue(new MoveItem(item.SourceModule, item.SourceSlot, item.DestinationModule, item.DestinationSlot, item.RobotHand));
            }

            var firtItem = _actionList.Peek();

            _moveTimeout = SC.GetValue<int>("EFEM.MotionTimeout") * 1000;
            _autoPumpOptInWafer = SC.GetValue<int>("EFEM.LLAutoPumpInWaferOpt");
            _autoPumpOptOutWafer = SC.GetValue<int>("EFEM.LLAutoPumpOutWaferOpt");

            _bAutoMode = Singleton<RouteManager>.Instance.IsAutoMode;

            _actionCount = _actionList.Count;
            return Runner.Start(Module, $"EFEM Swap with");
        }

        public RState Monitor()
        {
            Runner.LoopStart(SwapStep.MoveWafer, loopName(), _actionCount, MoveWafer)
                .LoopEnd(SwapStep.WaitMaferMoved, NullFun, WaitWaferMoved, _moveTimeout);

            return Runner.Status;
        }

        private bool ModulePrepare()
        {
            return true;
        }

        private string loopName()
        {
            return "EFEM Swap";
        }


        private bool VerifyWaferExistence(MoveItem item)
        {
            if (WaferManager.Instance.CheckHasWafer(item.DestinationModule, item.DestinationSlot))
            {
                LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Cannot move wafer as desitination {item.DestinationModule},{item.DestinationSlot} already a wafer: ");
                return false;
            }

            if (WaferManager.Instance.CheckNoWafer(item.SourceModule, item.SourceSlot))
            {
                LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Cannot move wafer as source {item.SourceModule}, {item.SourceSlot} has no wafer");
                return false;
            }

            return true;
        }

        private bool MoveWafer()
        {
            if(_actionList.Count <= 0)
            {
                Runner.Stop("no action");
                return true;
            }
            _currentAction = _actionList.Dequeue();

            if (!VerifyWaferExistence(_currentAction))
                return false;

            var wafer = WaferManager.Instance.GetWafer(_currentAction.SourceModule, _currentAction.SourceSlot);
            LOG.Write(eEvent.EV_EFEM_ROBOT, ModuleName.EfemRobot, $"{wafer.WaferOrigin} will be move from {_currentAction.SourceModule} {_currentAction.SourceSlot + 1}  to {_currentAction.DestinationModule} {_currentAction.DestinationSlot + 1}");


            return false;
        }

        private bool WaitWaferMoved()
        {
            if (_efem.Status == RState.Running)
            {
                return false;
            }
            else if (_efem.Status == RState.End)
            {
                WaferManager.Instance.WaferMoved(_currentAction.SourceModule, _currentAction.SourceSlot, _currentAction.DestinationModule, _currentAction.DestinationSlot);
                return true;
            }
            else
            {
                Runner.Stop($"EFEM Robot moving wafer failed, {_efem.Status}");
                return true;
            }
        }

        public void Abort()
        {
            _efem.Halt();
        }
    }
}