using Aitex.Core.Common;
using Aitex.Core.RT.Fsm;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using SicRT.Modules;
using SicRT.Modules.Schedulers;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Schedulers;
using MECF.Framework.Common.SubstrateTrackings;
using SicRT.Equipments;
using SicRT.Equipments.Systems;
using Aitex.Core.RT.Device;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs;
using Aitex.Core.RT.Device.Devices;
using Aitex.Core.RT.DataCenter;

namespace SicRT.Scheduler
{
    public class SchedulerPM : SchedulerModule
    {
        public override bool IsAvailable
        {
            get
            {
                if (SC.GetValue<bool>("System.IsATMMode"))
                {
                    return _pm.IsIdle && _pm.IsOnline && CheckTaskDone();
                }
                else
                {
                    return _pm.IsProcessIdle && _pm.IsOnline && CheckTaskDone();
                }
            }
        }

        public override bool IsOnline
        {
            get { return _pm.IsOnline; }
        }
        public override bool IsError
        {
            get { return _pm.IsError; }
        }

        public bool IsLineHeaterEnable
        {
            get { return (bool)DATA.Poll($"{_pm.Name}.OmronTemp.Enable"); }
        }

        public override bool IsService
        {
            get { return _pm.IsService; }
        }

        public override string State
        {
            get { return _pm.StringFsmStatus; }
        }


        private PMModuleBase _pm = null;

        private ModuleName _taskRobot;
        private EnumTransferType _taskTransferType;
        private int _taskSlot;
        private int _entityTaskToken = (int)FSM_MSG.NONE;

        private DeviceTimer _timer = new DeviceTimer();

        public SchedulerPM(ModuleName chamber) : base(chamber.ToString())
        {
            _pm = Singleton<EquipmentManager>.Instance.Modules[chamber] as PMModuleBase;
            System.Diagnostics.Trace.Assert(_pm != null);
        }

        public override bool IsReadyForPick(ModuleName robot, int slot)
        {
            return _pm.IsPrepareTransferReady(robot, EnumTransferType.Pick, slot);
        }

        public override bool IsReadyForPlace(ModuleName robot, int slot)
        {
            return _pm.IsPrepareTransferReady(robot, EnumTransferType.Place, slot);
        }

        public override bool PrepareTransfer(ModuleName robot, EnumTransferType type, int slot)
        {
            _task = TaskType.PrepareTransfer;
            _taskRobot = robot;
            _taskSlot = slot;
            _taskTransferType = type;
            _entityTaskToken = _pm.InvokePrepareTransfer(robot, type, slot);

            LogTaskStart(_task, $"{robot} {type} slot {slot + 1}");
            return _entityTaskToken != (int)FSM_MSG.NONE;
        }

        public override bool Process(string recipeName, bool isCleanRecipe, bool withWafer)
        {
            _task = TaskType.Process;

            if (SC.GetValue<bool>("System.IsATMMode"))
            {
                _timer.Start(5000);

                _entityTaskToken = (int)FSM_MSG.TIMER;

                WaferManager.Instance.GetWafer(Module, 0).ProcessState = WaferProcessStatus.InProcess;
            }
            else
            {
                _entityTaskToken = _pm.InvokeProcess(recipeName, isCleanRecipe, withWafer);
            }

            LogTaskStart(_task, $"recipe: {recipeName}, clean: {isCleanRecipe}, with wafer: {withWafer}");


            return _entityTaskToken != (int)FSM_MSG.NONE;
        }

        public bool CheckTaskDone()
        {
            bool ret = false;
            switch (_task)
            {
                case TaskType.None:
                    ret = true;
                    break;
                case TaskType.PrepareTransfer:
                    ret = _pm.CheckAcked(_entityTaskToken) && _pm.IsPrepareTransferReady(_taskRobot, _taskTransferType, _taskSlot);
                    break;
                case TaskType.Process:

                    if (SC.GetValue<bool>("System.IsATMMode"))
                    {
                        ret = _timer.IsTimeout();

                        if (ret)
                            WaferManager.Instance.GetWafer(Module, 0).ProcessState = WaferProcessStatus.Completed;
                    }
                    else
                    {
                        ret = _pm.CheckAcked(_entityTaskToken) && _pm.IsProcessed();

                    }

                    break;
            }

            if (ret && _task != TaskType.None)
            {
                LogTaskDone(_task, "");
                _task = TaskType.None;
            }

            return ret;
        }

        public bool Monitor()
        {
            return true;
        }

        //TMRobot从Buffer放到PM时检查
        public bool CheckBufferToPMTemp()
        {
            bool psuEnable = SC.GetValue<bool>($"PM.{Module}.PreTransferPSUEnable");
            bool scrEnable = SC.GetValue<bool>($"PM.{Module}.PreTransferSCREnable");

           if(!psuEnable)
            {
                _pm.ClosePSUEnable(out _);
            }

           if(!scrEnable)
            {
                _pm.CloseSCREnable(out _);
            }

            //IoInterLock pmIoInterLock = DEVICE.GetDevice<IoInterLock>($"{_module}.PMInterLock");
            //if (pmIoInterLock != null)
            //{
            //    return pmIoInterLock.DiHeaterTempBelow900CSW && _pm.CheckPlacetoPMTemp();
            //}

            //return false;

            return _pm.CheckPlacetoPMTemp();
        }

        //TMRobot从PM取Tray时检查
        public bool CheckPMToTMRobotTemp()
        {
            bool psuEnable = SC.GetValue<bool>($"PM.{Module}.PreTransferPSUEnable");
            bool scrEnable = SC.GetValue<bool>($"PM.{Module}.PreTransferSCREnable");

            if (!psuEnable)
            {
                _pm.ClosePSUEnable(out _);
            }

            if (!scrEnable)
            {
                _pm.CloseSCREnable(out _);
            }

            //IoInterLock pmIoInterLock = DEVICE.GetDevice<IoInterLock>($"{_module}.PMInterLock");
            //if (pmIoInterLock != null)
            //{
            //    return pmIoInterLock.DiHeaterTempBelow900CSW;
            //}

            //return false;

            return _pm.CheckPickFromPMTemp();
        }

        public bool CheckTempBelow900()
        {
            IoInterLock pmIoInterLock = DEVICE.GetDevice<IoInterLock>($"{_module}.PMInterLock");
            if (pmIoInterLock != null)
            {
                return pmIoInterLock.DiHeaterTempBelow900CSW;
            }

            return false;
        }

    }
}
