using System.Collections.Generic;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Routine;
using Aitex.Sorter.Common;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Schedulers;
using MECF.Framework.Common.SubstrateTrackings;
using SicRT.Modules.Schedulers;

namespace SicRT.Equipments
{
    public class MoveItemEx : MoveItem
    {
        public int CoolingTime { get; set; }

        public MoveItemEx(ModuleName sourceModule, int sourceSlot, ModuleName destinationModule, int destinationSlot, int coolingTime)
            : base(sourceModule, sourceSlot, destinationModule, destinationSlot, Hand.Blade1)
        {
            CoolingTime = coolingTime;
        }
    }

    public class ManualTransfer : SchedulerModuleFactory
    {
        private Queue<IRoutine> _moveTaskQueue = new Queue<IRoutine>();
        private IRoutine _activeTask;

        public Result Start(object[] objs)
        {
            _moveTaskQueue.Clear();

            ModuleName source = (ModuleName)objs[0];
            int sourceSlot = (int)objs[1];
            ModuleName target = (ModuleName)objs[2];
            int destinationSlot = (int)objs[3];

            //判断传盘路径是否valid
            if (!CheckCanMoveRange(source, target))
            {
                EV.PostWarningLog("System", $"Invalid path,can not transfer from {source} to {target}");
                return Result.DONE;
            }

            //TM范围内传盘
            if (IsTmRobotRange(source) && IsTmRobotRange(target))
            {
                if (!WaferManager.Instance.CheckHasTray(source, sourceSlot))
                {
                    EV.PostWarningLog("System", "source no tray");
                    return Result.FAIL;
                }
                if (!WaferManager.Instance.CheckNoTray(target, destinationSlot))
                {
                    EV.PostWarningLog("System", "destination has tray");
                    return Result.FAIL;
                }

                _moveTaskQueue.Enqueue(new TmRobotMover(new MoveItemEx(source, sourceSlot, target, destinationSlot, 0)));
            }

            _activeTask = _moveTaskQueue.Dequeue();

            return _activeTask.Start();
        }


        public Result Monitor(object[] objs)
        {
            Result ret = _activeTask.Monitor();
            if (ret == Result.FAIL)
                return ret;

            if (ret == Result.DONE)
            {
                if (_moveTaskQueue.Count > 0)
                {
                    _activeTask = _moveTaskQueue.Dequeue();
                    return _activeTask.Start();
                }

                return Result.DONE;
            }

            return Result.RUN;
        }

        public void Clear()
        {
            _moveTaskQueue.Clear();
            _activeTask = null;
        }

        private bool IsTmRobotRange(ModuleName module)
        {
            return module == ModuleName.LoadLock || module == ModuleName.Load || ModuleHelper.IsPm(module)
                || module == ModuleName.Buffer || module == ModuleName.TMRobot;
        }

        private bool CheckCanMoveRange(ModuleName fromModule, ModuleName desModule)
        {
            if (IsTmRobotRange(fromModule) && IsTmRobotRange(desModule))
            {
                return true;
            }

            return false;
        }
    }

    public class TmRobotMover : SchedulerModuleFactory, IRoutine
    {
        private MoveItemEx _moveTask;

        private SchedulerModule _source;
        private SchedulerModule _destination;

        public TmRobotMover(MoveItemEx moveTask)
        {
            _moveTask = moveTask;
        }

        public Result Start()
        {
            _source = GetModule(_moveTask.SourceModule.ToString());
            _destination = GetModule(_moveTask.DestinationModule.ToString());

            System.Diagnostics.Debug.Assert(_source != null, $"{_moveTask.SourceModule} not valid");
            System.Diagnostics.Debug.Assert(_destination != null, $"{_moveTask.DestinationModule} not valid");

            _source.ResetTask();
            _destination.ResetTask();
            _tmRobot.ResetTask();

            if (!WaferManager.Instance.CheckHasTray(_moveTask.SourceModule, _moveTask.SourceSlot))
            {
                EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} slot {_moveTask.SourceSlot + 1} has not tray");
                return Result.FAIL;
            }

            if (WaferManager.Instance.CheckHasTray(_moveTask.DestinationModule, _moveTask.DestinationSlot))
            {
                EV.PostWarningLog("System", $"Failed transfer, destination {_moveTask.DestinationModule} slot {_moveTask.DestinationSlot + 1} has tray");
                return Result.FAIL;
            }
            if (!_tmRobot.IsOnline)
            {
                EV.PostWarningLog("System", $"Failed transfer, TM is not online");
                return Result.FAIL;
            }
            if (!_source.IsAvailable)
            {
                EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} not ready");
                return Result.FAIL;
            }
            if (!_destination.IsAvailable)
            {
                EV.PostWarningLog("System", $"Failed transfer, Destination {_moveTask.DestinationModule} not ready");
                return Result.FAIL;
            }

            if (_moveTask.SourceModule == ModuleName.TMRobot)
                _moveTask.RobotHand = (Hand)_moveTask.SourceSlot;
            if (_moveTask.DestinationModule == ModuleName.TMRobot)
                _moveTask.RobotHand = (Hand)_moveTask.DestinationSlot;

            return Result.RUN;
        }
        public Result Start(params object[] objs)
        {
            return this.Start();
        }

        public Result Monitor()
        {
            if (_source.NoTray(_moveTask.SourceSlot) && _destination.HasTray(_moveTask.DestinationSlot) &&
                _tmRobot.IsAvailable)
            {
                if (_source.IsWaitTransfer(ModuleName.TMRobot))
                    _source.StopWaitTransfer(ModuleName.TMRobot);

                if (_destination.IsWaitTransfer(ModuleName.TMRobot))
                    _destination.StopWaitTransfer(ModuleName.TMRobot);

                return Result.DONE;
            }

            //Pick
            if (_moveTask.SourceModule != ModuleName.TMRobot)
            {
                if (_source.HasTray(_moveTask.SourceSlot))
                {
                    if (!_source.IsAvailable)
                    {
                        return Result.RUN;
                    }

                    if (!_tmRobot.IsAvailable)
                        return Result.RUN;

                    if (!_source.IsReadyForPick(ModuleName.TMRobot, _moveTask.SourceSlot))
                    {
                        if (!_source.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, _moveTask.SourceSlot))
                            return Result.FAIL;
                    }

                    if (!_source.IsAvailable)
                    {
                        return Result.RUN;
                    }

                    if (!_tmRobot.HasTray((int)_moveTask.RobotHand))
                    {
                        if (!_tmRobot.Pick(_moveTask.SourceModule, _moveTask.SourceSlot, _moveTask.RobotHand))
                        {
                            return Result.FAIL;
                        }

                        _source.WaitTransfer(ModuleName.TMRobot);
                    }
                }
                else
                {
                    if (!_tmRobot.IsAvailable)
                        return Result.RUN;

                    if (_source.IsWaitTransfer(ModuleName.TMRobot))
                        _source.StopWaitTransfer(ModuleName.TMRobot);
                }
            }

            //Place
            if (_moveTask.DestinationModule != ModuleName.TMRobot)
            {
                if (!_destination.IsAvailable)
                    return Result.RUN;

                if (!_tmRobot.IsAvailable)
                    return Result.RUN;

                if (_destination.NoTray(_moveTask.DestinationSlot))
                {
                    if (!_destination.IsReadyForPlace(ModuleName.TMRobot, _moveTask.DestinationSlot))
                    {
                        if (!_destination.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place,
                            _moveTask.DestinationSlot))
                            return Result.FAIL;
                    }

                    if (!_destination.IsAvailable)
                        return Result.RUN;

                    if (_tmRobot.HasTray((int)_moveTask.RobotHand))
                    {
                        if (!_tmRobot.Place(_moveTask.DestinationModule, _moveTask.DestinationSlot, _moveTask.RobotHand))
                            return Result.FAIL;

                        _destination.WaitTransfer(ModuleName.TMRobot);
                    }
                }
                else
                {
                    if (!_tmRobot.IsAvailable)
                        return Result.RUN;

                    if (_destination.IsWaitTransfer(ModuleName.TMRobot))
                        _destination.StopWaitTransfer(ModuleName.TMRobot);
                }
            }

            return Result.RUN;
        }
        public void Abort()
        {
            Clear();
        }

        public void Clear()
        {
            _tmRobot.ResetTask();
            _source?.ResetTask();
            _destination?.ResetTask();
        }
    }
}
