using Aitex.Core.Common;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using Aitex.Core.Util;
using Aitex.Sorter.Common;
using PunkHPX8_Core;
using PunkHPX8_RT.Devices.EFEM;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Schedulers;
using MECF.Framework.Common.SubstrateTrackings;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace PunkHPX8_RT.Modules.SRD
{
    internal class SRDAWCCycleRoutine : ModuleRoutineBase, IRoutine
    {
        private enum AWCStep
        {
            Ready,
            Speed50Percent,
            WaitSpeed50Percent,
            Speed80Percent,
            WaitSpeed80Percent,
            PickfromSRD,
            WaitPickfromSRD,
            LoopDelayPickSRD,
            PlacetoAligner0,
            WaitPlacetoAligner0,
            LoopDelayPlaceAligner0,
            Align0Degree,
            WaitAlign0Degree,
            LoopDelayAligner0,
            PickfromAligner0,
            WaitPickfromAligner0,
            LoopDelayPickAligner0,
            PlacetoAligner120,
            WaitPlacetoAligner120,
            LoopDelayPlaceAligner120,
            Align120Degree,
            WaitAlign120Degree,
            LoopDelayAligner120,
            PickfromAligner120,          
            WaitPickfromAligner120,
            LoopDelayPickAligner120,
            PlacetoAligner240,
            WaitPlacetoAligner240,
            LoopDelayPlaceAligner240,
            Align240Degree,
            WaitAlign240Degree,
            LoopDelayAligner240,
            PickfromAligner240,
            WaitPickfromAligner240,
            LoopDelayPickAligner240,
            PlacetoSRD,
            WaitPlacetoSRD,
            LoopDelayPlaceSRD,
            HomeSRD,
            WaitHomeSRD,            
            CycleEnd,
            End
        }
        #region 内部变量
        /// 
        /// 次数
        /// 
        private int _cycleCount = 0;
        /// 
        /// 超时时间
        /// 
        private int _timeOut = 2000;
        /// 
        /// Efem Enitity
        /// 
        private EfemEntity _efemEntity;
        /// 
        /// Efem Device
        /// 
        private EfemBase _efemDevice;
        /// 
        /// SRD Module Name
        /// 
        private ModuleName _srdModuleName;
        /// 
        /// SRD Entity
        /// 
        private SRDEntity _srdEntity;
        #endregion
        #region 属性
        /// 
        /// 当前子状态机
        /// 
        public string CurrentStateMachine
        {
            get { return Runner.CurrentStep.ToString(); }
        }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public SRDAWCCycleRoutine(ModuleName module) : base(module)
        {
            Name = "AWCCycle";
            _srdModuleName = module;
        }
        /// 
        /// Abort
        /// 
        public void Abort()
        {
            Runner.Stop("SRD AWC Cycle Abort");
        }
        /// 
        /// Monitor
        /// 
        /// 
        public RState Monitor()
        {
            Runner.LoopStart(AWCStep.Ready, "AWC Cycle", _cycleCount, NullFun, CheckReady, _timeOut)
                 //Robot speed 50%  and pick wafer from SRD
                .LoopRun(AWCStep.Speed50Percent, ()=> { return RobotSpeed(50); }, _delay_2s)
                .LoopRunWithStopStatus(AWCStep.WaitSpeed50Percent, CheckOperationComplete, CheckOperationError)
                .LoopRun(AWCStep.PickfromSRD, PickFromSRD, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitPickfromSRD, CheckOperationComplete, CheckOperationError)
                .LoopDelay(AWCStep.LoopDelayPickSRD, _delay_2s)
                //Robot place wafer to Aligner, Align wafer 0 deg, pick from Aligner
                .LoopRun(AWCStep.PlacetoAligner0, PlacetoAligner, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitPlacetoAligner0, CheckOperationComplete, CheckOperationError)
                .LoopDelay(AWCStep.LoopDelayPlaceAligner0, _delay_2s)
                .LoopRun(AWCStep.Align0Degree, () => { return Align(0); }, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitAlign0Degree, CheckOperationComplete, CheckOperationError)
                .LoopDelay(AWCStep.LoopDelayAligner0, _delay_2s)
                .LoopRun(AWCStep.PickfromAligner0, PickfromAligner, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitPickfromAligner0, CheckOperationComplete, CheckOperationError)
                .LoopDelay(AWCStep.LoopDelayPickAligner0, _delay_2s)
                //Robot place wafer to Aligner, Align wafer 120 deg, pick from Aligner
                .LoopRun(AWCStep.PlacetoAligner120, PlacetoAligner, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitPlacetoAligner120, CheckOperationComplete, CheckOperationError)
                .LoopDelay(AWCStep.LoopDelayPlaceAligner120, _delay_2s)
                .LoopRun(AWCStep.Align120Degree, () => { return Align(120); }, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitAlign120Degree, CheckOperationComplete, CheckOperationError)
                .LoopDelay(AWCStep.LoopDelayAligner120, _delay_2s)
                .LoopRun(AWCStep.PickfromAligner120, PickfromAligner, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitPickfromAligner120, CheckOperationComplete, CheckOperationError)
                .LoopDelay(AWCStep.LoopDelayPickAligner120, _delay_2s)
                //Robot place wafer to Aligner, Align wafer 240 deg, pick from Aligner
                .LoopRun(AWCStep.PlacetoAligner240, PlacetoAligner, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitPlacetoAligner240, CheckOperationComplete, CheckOperationError)
                .LoopDelay(AWCStep.LoopDelayPlaceAligner240, _delay_2s)
                .LoopRun(AWCStep.Align240Degree, () => { return Align(240); }, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitAlign240Degree, CheckOperationComplete, CheckOperationError)
                .LoopDelay(AWCStep.LoopDelayAligner240, _delay_2s)
                .LoopRun(AWCStep.PickfromAligner240, PickfromAligner, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitPickfromAligner240, CheckOperationComplete, CheckOperationError)
                .LoopDelay(AWCStep.LoopDelayPickAligner240, _delay_2s)
                //Robot speed80% place wafer to SRD
                .LoopRun(AWCStep.Speed80Percent, () => { return RobotSpeed(80); }, _delay_2s)
                .LoopRunWithStopStatus(AWCStep.WaitSpeed80Percent, CheckOperationComplete, CheckOperationError)
                .LoopRun(AWCStep.PlacetoSRD, PlacetoSRD, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitPlacetoSRD, CheckOperationComplete, CheckOperationError)
                .LoopDelay(AWCStep.LoopDelayPlaceSRD, _delay_2s)
                .LoopRun(AWCStep.HomeSRD, HomeSRD, _delay_50ms)
                .LoopRunWithStopStatus(AWCStep.WaitHomeSRD, CheckHomeSRDComplete, CheckHomeSRDError)
                .LoopEnd(AWCStep.CycleEnd, NullFun, CheckOperationComplete)
                .End(AWCStep.End, NullFun, _delay_1ms);
            return Runner.Status;
        }
        /// 
        /// 检验Ready状态
        /// 
        /// 
        private bool CheckReady()
        {
            //检查是否有Wafer
            if (!WaferManager.Instance.CheckHasWafer(_srdModuleName, 0))
            {
                LOG.Write(eEvent.ERR_SRD, Module, $"{Module} don't have wafer, can't do AWC Cycle");
                return false;
            }
            _srdEntity = Singleton.Instance.GetModule(Module.ToString());
            //检查SRD Home
            if (!_srdEntity.IsHomed)
            {
                LOG.Write(eEvent.ERR_SRD, Module, $"{Module} is not homed, can't do AWC Cycle. Please home it first");
                return false;
            }
            //检查SRD门是否关闭
            if (_srdEntity.IsSrdDoorClosed)
            {
                LOG.Write(eEvent.ERR_SRD, Module, $"{Module} door closed, can't do AWC Cycle");
                return false;
            }
            //检查SRD真空是否开启
            if (!_srdEntity.IsSrdChuckVacuum)
            {
                LOG.Write(eEvent.ERR_SRD, Module, $"{Module} Vacuum on, can't do AWC Cycle");
                return false;
            }
            //检查EFEM状态
            if (_efemEntity.IsIdle) return true;
            return false;
        }
        /// 
        /// Robot speed
        /// 
        /// 
        private bool RobotSpeed(int speed)
        {
            _efemEntity.CheckToPostMessage(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM.ToString(), (int)EfemEntity.MSG.SetRobotSpeed, speed);
            return true;
        }      
        /// 
        /// Pick from SRD
        /// 
        /// 
        private bool PickFromSRD()
        {
            Queue moveItems = new Queue();
            MoveItem moveItem = new MoveItem(_srdModuleName, 0, ModuleName.EfemRobot, 0, Hand.Blade1, Flip.Upper, Flip.Upper);
            moveItems.Enqueue(moveItem);
            return _efemEntity.CheckToPostMessage(eEvent.ERR_EFEM_COMMON_FAILED, "EFEM", (int)EfemEntity.MSG.Pick, moveItems);           
        }
        /// 
        /// Place to SRD
        /// 
        /// 
        private bool PlacetoSRD()
        {
            Queue moveItems = new Queue();
            MoveItem moveItem = new MoveItem(ModuleName.EfemRobot, 0, _srdModuleName, 0, Hand.Blade1,Flip.Upper, Flip.Upper);
            moveItems.Enqueue(moveItem);
            return _efemEntity.CheckToPostMessage(eEvent.ERR_EFEM_COMMON_FAILED, "EFEM", (int)EfemEntity.MSG.Place, moveItems);
        }
        /// 
        /// Pick from Aligner
        /// 
        /// 
        private bool PickfromAligner()
        {
            Queue moveItems = new Queue();
            MoveItem moveItem = new MoveItem(ModuleName.Aligner1, 0, ModuleName.EfemRobot, 0, Hand.Blade1, Flip.Upper,Flip.Upper);
            moveItems.Enqueue(moveItem);
            return _efemEntity.CheckToPostMessage(eEvent.ERR_EFEM_COMMON_FAILED, "EFEM", (int)EfemEntity.MSG.Pick, moveItems);
        }
        /// 
        /// Place to Aligner
        /// 
        /// 
        private bool PlacetoAligner()
        {
            Queue moveItems = new Queue();
            MoveItem moveItem = new MoveItem(ModuleName.EfemRobot, 0, ModuleName.Aligner1, 0, Hand.Blade1,Flip.Upper,Flip.Upper);
            moveItems.Enqueue(moveItem);
            return _efemEntity.CheckToPostMessage(eEvent.ERR_EFEM_COMMON_FAILED, "EFEM", (int)EfemEntity.MSG.Place, moveItems);
        }     
        /// 
        /// Align to target degree
        /// 
        /// 
        /// 
        private bool Align(int degree)
        {
            return _efemEntity.CheckToPostMessage(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM.ToString(), (int)EfemEntity.MSG.Align, ModuleName.Aligner1, 0, degree); ;
        }      
        /// 
        /// 检查Operation是否完成
        /// 
        /// 
        private bool CheckOperationComplete()
        {
            if (_efemEntity.IsIdle && _efemEntity.RobotStatus == RState.End)
            {
                //LOG.WriteLog(eEvent.ERR_PREWET, _srdModuleName.ToString(), $"Efem RSstate is {_efemEntity.RobotStatus}");
                return true;
            }
            return false;
        }
        /// 
        /// 检查是Operation是否报错
        /// 
        /// 
        private bool CheckOperationError()
        {
            if (_efemEntity.IsError || _efemEntity.RobotStatus == RState.Failed || _efemEntity.RobotStatus == RState.Timeout)
            {
                _srdEntity.SetIsAWCCycling(false);
                LOG.WriteLog(eEvent.ERR_SRD, _srdModuleName.ToString(), $"Step {Runner.CurrentStep} is Error");
                return true;
            }
            return false;
        }       
        /// 
        /// Home SRD
        /// 
        /// 
        private bool HomeSRD()
        {         
            return _srdEntity.CheckToPostMessage(eEvent.ERR_SRD, Module.ToString(), (int)SRDMSG.HomeAll);
        }
        /// 
        /// 检查SRD Home是否完成
        /// 
        /// 
        private bool CheckHomeSRDComplete()
        {
            if(_srdEntity.IsHomed) return true;
            return false;
        }
        /// 
        /// 检查SRD Home是否报错
        /// 
        /// 
        private bool CheckHomeSRDError()
        {
            if (_srdEntity.IsError)
            {
                _srdEntity.SetIsAWCCycling(false);
                LOG.WriteLog(eEvent.ERR_SRD, _srdModuleName.ToString(), $"Step {Runner.CurrentStep} is Error");
                return true;
            }
            return false;
        }
        /// 
        /// Start
        /// 
        /// 
        /// 
        public RState Start(params object[] objs)
        {          
            _cycleCount = (int)objs[0];
            _efemEntity = Singleton.Instance.GetModule(ModuleName.EFEM.ToString());
            _efemDevice = _efemEntity.EfemDevice;
            Runner.Start(Module, Name);
            return RState.Running;
        }
    }
}