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

namespace SicRT.Modules
{
    public class ReturnAllWafer : SchedulerModuleFactory
    {
        //private bool needAligner = false; 
        Dictionary<ModuleName, int> _checkPosition = new Dictionary<ModuleName, int>()
        {
            {ModuleName.PM1, 1},
            {ModuleName.LoadLock, 1},
            {ModuleName.UnLoad, 1},
            {ModuleName.WaferRobot, 1},
            {ModuleName.TrayRobot, 1},
            {ModuleName.TMRobot, 1},
            {ModuleName.Aligner, 1},
        };


        public ReturnAllWafer()
        {
        }

        public Result Start()
        {
            if (!_tmRobot.IsAvailable)
            {
                EV.PostWarningLog("Scheduler", "can not return wafer, TmRobort is not available!");
                return Result.FAIL;
            }
            if (!_trayRobot.IsAvailable)
            {
                EV.PostWarningLog("Scheduler", "can not return wafer, TrayRobort is not available!");
                return Result.FAIL;
            }
            if (!_waferRobot.IsAvailable)
            {
                EV.PostWarningLog("Scheduler", "can not return wafer, WaferRobort is not available!");
                return Result.FAIL;
            }
            if (!_load.IsAvailable)
            {
                EV.PostWarningLog("Scheduler", "can not return wafer, Load is not available!");
                return Result.FAIL;
            }
            if (!_unload.IsAvailable)
            {
                EV.PostWarningLog("Scheduler", "can not return wafer, UnLoad is not available!");
                return Result.FAIL;
            }
            if (!_buffer.IsAvailable)
            {
                EV.PostWarningLog("Scheduler", "can not return wafer, Buffer is not available!");
                return Result.FAIL;
            }

            return Result.RUN;
        }

        public Result Monitor()
        {
            MonitorModuleTasks();

            if (MonitorTaskDone())
            {
                return Result.DONE;
            }


            return Result.RUN;
        }

        public Result MonitorModuleTasks()
        {
            //Load和UnLoad不能同时抽气
            //System.Diagnostics.Debug.Assert(!((_tmRobot.IsInPumping && _load.IsInPumping) || (_tmRobot.IsInPumping && _unload.IsInPumping) || (_unload.IsInPumping && _load.IsInPumping)), $"检测到 _load.IsInPumping :{_load.IsInPumping}, _unload.IsInPumping :{_unload.IsInPumping}, _tmRobot.IsInPumping :{_tmRobot.IsInPumping}");


            MonitorPMTask();
            MonitorLoadTask();
            MonitorUnLoadTask();
            MonitorBufferTask();
            MonitorAlignerTask();

            MonitorTmRobotTask();
            MonitorWaferRobotTask();
            MonitorTrayRobotTask();


            return Result.RUN;
        }

        private bool MonitorTaskDone()
        {
            foreach (var positions in _checkPosition)
            {
                for (int i = 0; i < positions.Value; i++)
                {
                    if (CheckWaferCouldBeReturn(positions.Key, i))
                    {
                        return false;
                    }
                }
            }

            if (_buffer.HasWafer(0) || _buffer.HasWafer(1) || _buffer.HasWafer(2))
                return false;
            if (_buffer.HasTrayAndExceedProcessCount(0) || _buffer.HasTrayAndExceedProcessCount(1) || _buffer.HasTrayAndExceedProcessCount(2))
                return false;

            if (!_tmRobot.IsAvailable)
                return false;
            if (!_waferRobot.IsAvailable)
                return false;
            if (!_trayRobot.IsAvailable)
                return false;

            return true;
        }

        private void MonitorTmRobotTask()
        {
            if (!_tmRobot.IsAvailable)
                return;

            foreach (var pm in _lstPms)
            {
                if (pm.IsWaitTransfer(ModuleName.TMRobot))
                    pm.StopWaitTransfer(ModuleName.TMRobot);
            }

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

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

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

            MonitorTmRobotPMTask();

            MonitorTmRobotBufferTask();

            MonitorTmRobotLoadTask();

            MonitorTmRobotUnLoadTask();
        }

        private void MonitorWaferRobotTask()
        {
            foreach (var cass in _lstWaferCassettes)
            {
                if (cass.IsWaitTransfer(ModuleName.WaferRobot))
                    cass.StopWaitTransfer(ModuleName.WaferRobot);
            }

            if (_aligner.IsWaitTransfer(ModuleName.WaferRobot))
                _aligner.StopWaitTransfer(ModuleName.WaferRobot);

            if (_load.IsWaitTransfer(ModuleName.WaferRobot))
                _load.StopWaitTransfer(ModuleName.WaferRobot);

            if (_unload.IsWaitTransfer(ModuleName.WaferRobot))
                _unload.StopWaitTransfer(ModuleName.WaferRobot);

            MonitorWaferRobotCassetteTask();
            MonitorWaferRobotAligerTask();
            MonitorWaferRobotLoadTask();
            MonitorWaferRobotUnLoadTask();
        }

        private void MonitorTrayRobotTask()
        {
            if (_cassetteBL.IsWaitTransfer(ModuleName.TrayRobot))
                _cassetteBL.StopWaitTransfer(ModuleName.TrayRobot);

            if (_load.IsWaitTransfer(ModuleName.TrayRobot))
                _load.StopWaitTransfer(ModuleName.TrayRobot);

            MonitorTrayRobotLoadTask();

            MonitorTrayRobotCassetteTask();
        }


        private void MonitorTmRobotLoadTask()
        {
            if (!_load.IsAvailable)
                return;
            if (!_tmRobot.IsAvailable)
                return;

            //place Robot有次数耗尽的Tray无Wafer,Load无Tray
            bool canPlace = _tmRobot.HasTrayAndExceedProcessCount(0) && _tmRobot.NoWafer(0) && _load.NoTray(0);
            if (canPlace)
            {
                if (_load.IsReadyForPlace(ModuleName.TMRobot, 0))
                {
                    if (_tmRobot.Place(_load.Module, 0, Hand.Blade1))
                    {
                        _load.WaitTransfer(ModuleName.TMRobot);
                        return;
                    }
                }
            }
        }

        private void MonitorTmRobotUnLoadTask()
        {
            if (!_unload.IsAvailable)
                return;
            if (!_tmRobot.IsAvailable)
                return;

            //UnLoad取盘只关心LoadLock是否有空位

            //place Robot有Wafer,UnLoad无Tray无Wafer
            bool canPlaceUnLoad = _tmRobot.HasWafer(0)
                                  && _unload.NoTray(0)
                                  && _unload.NoWafer(0);
            if (canPlaceUnLoad)
            {
                if (_unload.IsReadyForPlace(ModuleName.TMRobot, 0))
                {
                    if (_tmRobot.Place(_unload.Module, 0, Hand.Blade1))
                    {
                        _unload.WaitTransfer(ModuleName.TMRobot);
                        return;
                    }
                }
            }


            if (!_unload.IsAvailable)
                return;
            if (!_tmRobot.IsAvailable)
                return;

            //pick UnLoad有Tray,TM无Tray,UnLoad分离完成
            bool canPickUnLoad = _tmRobot.NoTray(0)
                                 && _unload.HasTray(0)
                                 && _unload.CheckWaferTraySeparated();
            if (canPickUnLoad)
            {
                if (_unload.IsReadyForPick(ModuleName.TMRobot, 0) && !_load.IsInPumping)
                {
                    if (_tmRobot.Pick(_unload.Module, 0, Hand.Blade1))
                    {
                        _unload.WaitTransfer(ModuleName.TMRobot);
                        return;
                    }
                }
            }
        }

        private void MonitorTmRobotBufferTask()
        {
            if (!_tmRobot.IsAvailable)
                return;
            if (!_buffer.IsAvailable)
                return;

            //place 次数未耗尽的Tray放入Buffer中
            bool canPalce = _tmRobot.NoWafer(0) && _tmRobot.HasTrayAndNotExceedProcessCount(0);
            if (canPalce)
            {
                SlotItem bufferEmptySlot = null;
                for (int i = 0; i < 3; i++)
                {
                    if (_buffer.NoTray(i) && _buffer.NoWafer(i))
                    {
                        bufferEmptySlot = new SlotItem(ModuleName.Buffer, i);
                        break;
                    }
                }

                if (bufferEmptySlot == null)
                {
                    return;
                }

                if (_buffer.IsReadyForPlace(ModuleName.TMRobot, bufferEmptySlot.Slot))
                {
                    if (_tmRobot.Place(_buffer.Module, bufferEmptySlot.Slot, Hand.Blade1))
                    {
                        _buffer.WaitTransfer(ModuleName.TMRobot);
                        return;
                    }
                }

            }


            if (!_tmRobot.IsAvailable)
                return;
            if (!_buffer.IsAvailable)
                return;

            //pick 当前步(UnLoad没有Wafer),Buffer有Tray,机械手没有Tray
            bool canPick = _tmRobot.NoTray(0) && _unload.NoTray(0) && _unload.NoWafer(0);
            if (canPick)
            {
                for (int i = 0; i < 3; i++)
                {
                    if (_buffer.HasTray(i) && _buffer.HasWafer(i))
                    {
                        if (_buffer.IsReadyForPick(ModuleName.TMRobot, i))
                        {
                            if (_tmRobot.Pick(_buffer.Module, i, Hand.Blade1))
                            {
                                _buffer.WaitTransfer(ModuleName.TMRobot);
                                return;
                            }
                        }
                    }

                    if (_buffer.HasTrayAndExceedProcessCount(i))
                    {
                        if (_buffer.IsReadyForPick(ModuleName.TMRobot, i))
                        {
                            if (_tmRobot.Pick(_buffer.Module, i, Hand.Blade1))
                            {
                                _buffer.WaitTransfer(ModuleName.TMRobot);
                                return;
                            }
                        }
                    }

                }
            }

        }

        private void MonitorTmRobotPMTask()
        {
            if (!_tmRobot.IsAvailable)
                return;

            //pick from pm
            if (_tmRobot.NoWafer(0) && _tmRobot.NoTray(0) && _unload.NoWafer(0) && _unload.NoTray(0))
            {
                Hand pickBlade = Hand.Blade1;

                ModuleName pickPm = ModuleName.System;
                foreach (var schedulerPm in _lstPms)
                {
                    //增加温度低于900才能Pick的限制
                    if (!schedulerPm.IsAvailable
                        || GetModule(schedulerPm.Module).NoWafer(0)
                        || _tmRobot.HasWafer((int)pickBlade))
                    {
                        continue;
                    }
                       
                    if(!schedulerPm.CheckPMToTMRobotTemp())
                    {
                        continue;
                    }

                    pickPm = schedulerPm.Module;
                    break;
                }

                if (pickPm != ModuleName.System)
                {
                    SchedulerModule pm = GetModule(pickPm.ToString());
                    if (pm.IsReadyForPick(ModuleName.TMRobot, 0))
                    {
                        if (_tmRobot.Pick(pm.Module, 0, pickBlade))
                        {
                            pm.WaitTransfer(ModuleName.TMRobot);

                            return;
                        }
                    }
                }
            }
        }

        private void MonitorWaferRobotLoadTask()
        {
            if (!_waferRobot.IsAvailable)
                return;
            if (!_load.IsAvailable)
                return;

            bool canPick = _waferRobot.NoWafer(0)
                            && _load.HasWafer(0);
            //&& _load.CheckWaferTraySeparated();

            if (canPick)
            {
                if (_load.IsReadyForPick(ModuleName.WaferRobot, 0))
                {
                    if (_waferRobot.Pick(_load.Module, 0, Hand.Blade1))
                    {
                        _load.WaitTransfer(ModuleName.WaferRobot);
                        return;
                    }
                }
            }
        }

        private void MonitorWaferRobotUnLoadTask()
        {
            if (!_waferRobot.IsAvailable)
                return;
            if (!_unload.IsAvailable)
                return;

            //pick UnLoad有Wafer没有Tray,Robot没有Wafer,步骤都完成了或者下一步的模块没有片子  (其它:UnLoad 夹爪夹住,顶针下降,SlitValve都关了,大气)
            bool canPick = _waferRobot.NoWafer(0)
                           && _unload.HasWafer(0)
                           && _unload.NoTray(0);

            if (canPick)
            {
                if (_unload.IsReadyForPick(ModuleName.WaferRobot, 0))
                {
                    if (_waferRobot.Pick(_unload.Module, 0, Hand.Blade1))
                    {
                        _unload.WaitTransfer(ModuleName.WaferRobot);
                        return;
                    }
                }
            }
        }

        private void MonitorWaferRobotAligerTask()
        {
            if (_load.HasWafer(0) && _load.GetWaferInfo(0).NextStation != (int)ModuleName.Aligner)
                _load.GetWaferInfo(0).NextStation = (int)ModuleName.Aligner;

            if (_unload.HasWafer(0) && _unload.GetWaferInfo(0).NextStation != (int)ModuleName.Aligner)
                _unload.GetWaferInfo(0).NextStation = (int)ModuleName.Aligner;

            if (_waferRobot.HasWafer(0) && _waferRobot.GetWaferInfo(0).NextStation != (int)ModuleName.Aligner && _waferRobot.GetWaferInfo(0).NextStation != (int)ModuleName.System)
                _waferRobot.GetWaferInfo(0).NextStation = (int)ModuleName.Aligner;

            if (!_waferRobot.IsAvailable)
                return;

            if (!_aligner.IsAvailable)
                return;

            //place 任务还没完成,下一步是Aligner,Robot有片子,Aligner没片子
            bool canPlaceAligner = _aligner.NoWafer(0)
                && _waferRobot.HasWafer(0)
                && _waferRobot.GetWaferInfo(0).NextStation == (int)ModuleName.Aligner;
            if (canPlaceAligner)
            {
                if (_aligner.IsReadyForPlace(ModuleName.WaferRobot, 0))
                {
                    if (_waferRobot.Place(_aligner.Module, 0, Hand.Blade1))
                    {
                        _aligner.WaitTransfer(ModuleName.WaferRobot);
                        return;
                    }
                }
            }


            if (!_waferRobot.IsAvailable)
                return;

            if (!_aligner.IsAvailable)
                return;

            //pick Robot没片子,Aligner有片子
            bool canPickAligner = _aligner.HasWafer(0)
                && _waferRobot.NoWafer(0);

            if (canPickAligner)
            {
                if (_aligner.IsReadyForPick(ModuleName.WaferRobot, 0))
                {
                    if (_waferRobot.Pick(_aligner.Module, 0, Hand.Blade1))
                    {
                        _aligner.WaitTransfer(ModuleName.WaferRobot);
                        return;
                    }
                }
            }
        }

        private void MonitorWaferRobotCassetteTask()
        {
            if (!_waferRobot.IsAvailable)
                return;

            //place
            bool canPlaceCassette = _waferRobot.HasWafer(0)&& _waferRobot.GetWaferInfo(0).NextStation!=(int)ModuleName.Aligner;
            if (canPlaceCassette)
            {
                var wafer = _waferRobot.GetWaferInfo(0);
                if (wafer.WaferOriginStation == ModuleName.CassAL.ToString())
                {
                    if (_cassetteAL.IsReadyForPlace(ModuleName.WaferRobot, wafer.WaferOriginSlot) && WaferManager.Instance.CheckNoWafer(ModuleName.CassAL, wafer.WaferOriginSlot))
                    {
                        if (_waferRobot.Place(_cassetteAL.Module, wafer.WaferOriginSlot, Hand.Blade1))
                        {
                            _cassetteAL.WaitTransfer(ModuleName.WaferRobot);
                            return;
                        }
                    }
                }
                else if (wafer.WaferOriginStation == ModuleName.CassAR.ToString())
                {
                    if (_cassetteAR.IsReadyForPlace(ModuleName.WaferRobot, wafer.WaferOriginSlot) && WaferManager.Instance.CheckNoWafer(ModuleName.CassAR, wafer.WaferOriginSlot))
                    {
                        if (_waferRobot.Place(_cassetteAR.Module, wafer.WaferOriginSlot, Hand.Blade1))
                        {
                            _cassetteAR.WaitTransfer(ModuleName.WaferRobot);
                            return;
                        }
                    }
                }
            }
        }

        private void MonitorTrayRobotLoadTask()
        {
            if (!_trayRobot.IsAvailable)
                return;
            if (!_load.IsAvailable)
                return;

            //先取Wafer再取石墨盘
            bool canPick = _load.HasTray(0) && _load.NoWafer(0);
            if (canPick)
            {
                SlotItem emptyTraySlot = GetTrayOrignSlot(ModuleName.LoadLock, 0);
                if (emptyTraySlot != null)
                {
                    if (_load.IsReadyForPick(ModuleName.TrayRobot, 0))
                    {
                        if (_trayRobot.Pick(_load.Module, 0, Hand.Blade1))
                        {
                            _load.WaitTransfer(ModuleName.TrayRobot);
                            return;
                        }
                    }
                }
            }

        }

        private void MonitorTrayRobotCassetteTask()
        {
            if (!_trayRobot.IsAvailable)
                return;

            if (!_cassetteBL.IsAvailable)
                return;

            //place Robot有盘 其它逻辑跟Load的Pick一致
            bool canPlace = _trayRobot.HasTray(0);
            if (canPlace)
            {
                SlotItem slotItem = GetTrayOrignSlot(ModuleName.TrayRobot, 0); //GetEmptyTraySlot(13);
                if (slotItem != null)
                {
                    if (_cassetteBL.IsReadyForPlace(ModuleName.TrayRobot, slotItem.Slot))
                    {
                        if (_trayRobot.Place(slotItem.Module, slotItem.Slot, Hand.Blade1))
                        {
                            _cassetteBL.WaitTransfer(ModuleName.TrayRobot);
                            return;
                        }
                    }
                }
            }

        }


        private void MonitorBufferTask()
        {
            if (!_buffer.IsAvailable)
            {
                return;
            }

            if (!_buffer.IsReadyForPick(ModuleName.TMRobot, 0))
            {
                _buffer.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
            }
        }

        private void MonitorAlignerTask()
        {
            if (!_aligner.IsAvailable)
            {
                return;
            }

            if (_aligner.HasWafer(0) && _aligner.GetWaferInfo(0).NextStation==(int)ModuleName.Aligner)
            {
                _aligner.Aligning();
                _aligner.GetWaferInfo(0).NextStation = (int)ModuleName.System;
            }
        }

        private void MonitorPMTask()
        {
            foreach (var pm in _lstPms)
            {
                if (!pm.IsAvailable)
                    continue;
                if (pm.NoTray(0) && pm.NoWafer(0))
                    continue;

                if (!pm.IsReadyForPick(ModuleName.TMRobot, 0))
                {
                    pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
                }
            }
        }

        private void MonitorLoadTask()
        {
            if (!_load.IsAvailable)
            {
                return;
            }

            //bool canExcute = _load.HasWafer(0) ;
            //if (canExcute)
            //{
            //    if (!_load.CheckWaferTraySeparated())
            //    {
            //        _load.SeparateWaferTray();
            //        return;
            //    }
            //}

            if (_load.HasWafer(0))
            {
                if (/*_load.CheckWaferTraySeparated() &&*/ !_load.IsReadyForPick(ModuleName.WaferRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
                {
                    _load.PrepareTransfer(ModuleName.WaferRobot, EnumTransferType.Pick, 0);
                    return;
                }
            }
            else if (_load.HasTray(0))
            {
                if (/*_load.CheckWaferTraySeparated() &&*/ !_load.IsReadyForPick(ModuleName.TrayRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
                {
                    _load.PrepareTransfer(ModuleName.TrayRobot, EnumTransferType.Pick, 0);
                    return;
                }
            }

            else if (_tmRobot.HasTrayAndExceedProcessCount(0) && _tmRobot.NoWafer(0))
            {
                if (!_load.IsReadyForPlace(ModuleName.TMRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
                {
                    _load.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
                    return;
                }
            }

        }

        private void MonitorUnLoadTask()
        {
            if (!_unload.IsAvailable)
            {
                return;
            }

            bool canExcuteUnLoad = _unload.HasWafer(0);
            if (canExcuteUnLoad)
            {
                if (!_unload.CheckWaferTraySeparated())
                {
                    _unload.SeparateWaferTray();
                    return;
                }
            }

            if (_unload.HasTray(0))
            {
                if (/*_unload.CheckWaferTraySeparated() && */!_unload.IsReadyForPick(ModuleName.TMRobot, 0) && !_load.IsInPumping && !_tmRobot.IsInPumping)
                {
                    _unload.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
                    return;
                }
            }
            else if (_unload.HasWafer(0))
            {
                if (_unload.CheckWaferTraySeparated() && !_unload.IsReadyForPick(ModuleName.WaferRobot, 0) && !_load.IsInPumping && !_tmRobot.IsInPumping)
                {
                    _unload.PrepareTransfer(ModuleName.WaferRobot, EnumTransferType.Pick, 0);
                    return;
                }
            }
            else
            {
                if (!_unload.IsReadyForPlace(ModuleName.TMRobot, 0) && !_load.IsInPumping && !_tmRobot.IsInPumping)
                {
                    _unload.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
                    return;
                }
            }
        }

        private SlotItem GetEmptyTraySlot()
        {
            for (int i = 0; i < WaferManager.Instance.GetWafers(ModuleName.CassBL).Length; i++)
            {
                if (WaferManager.Instance.CheckNoTray(ModuleName.CassBL, i))
                {
                    return new SlotItem(ModuleName.CassBL, i);
                }
            }
            return null;
        }

        private SlotItem GetTrayOrignSlot(ModuleName module, int slot)
        {
            var wafer = GetModule(module).GetWaferInfo(slot);
            if (wafer != null && GetModule(module).HasTray(slot) && _cassetteBL.NoTray(wafer.TrayOriginSlot))
            {
                return new SlotItem(ModuleName.CassBL, wafer.TrayOriginSlot);
            }
            return null;
        }

        private bool CheckWaferCouldBeReturn(ModuleName module, int slot)
        {
            var wafer = WaferManager.Instance.GetWafer(module, slot);
            if (!wafer.IsWaferEmpty)
            {
                return true;
            }
            else if (wafer.TrayStatus == TrayStatus.Normal)
            {
                return true;
            }

            return false;
        }
    }

}
