using Aitex.Core.RT.Routine;
using MECF.Framework.Common.Routine;
using CyberX8_Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace CyberX8_RT.Modules.LPs
{
    sealed class LoadPortCycleLoadUnloadRoutine : RoutineBase, IRoutine
    {
        private enum CycleLoadStep
        {
            LoopStart,
            LoopLoad,
            LoopLoadWait,
            LoopDelay,
            LoopUnload,
            LoopUnloadWait,
            LoopEnd,
            End
        }

        #region 内部变量
        private LoadPortModule _loadPortModule;
        private LoadPortLoadRoutine _loadRoutine;
        private LoadPortUnloadRoutine _unloadRoutine;
        private int _cycle = 0;
        #endregion
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="module"></param>
        public LoadPortCycleLoadUnloadRoutine(LoadPortModule loadPortModule) : base(loadPortModule.Module)
        {
            _loadRoutine = new LoadPortLoadRoutine(loadPortModule);
            _unloadRoutine=new LoadPortUnloadRoutine(loadPortModule);
            _loadPortModule = loadPortModule;
        }

        /// <summary>
        /// Abort
        /// </summary>
        public void Abort()
        {
            Runner.Stop("Manual Abort");
        }

        public RState Monitor()
        {
            Runner.LoopStart(CycleLoadStep.LoopStart, "Loop Start Load/Uload", _cycle, NullFun, _delay_1ms)
                .LoopRun(CycleLoadStep.LoopLoad, () => _loadRoutine.Start() == RState.Running, _delay_1ms)
                .LoopRunWithStopStatus(CycleLoadStep.LoopLoadWait, () => CheckRoutineEndStatus(_loadRoutine), () => CheckRoutineStopStatus(_loadRoutine))
                .LoopDelay(CycleLoadStep.LoopDelay,_delay_2s)
                .LoopRun(CycleLoadStep.LoopUnload, () => _unloadRoutine.Start() == RState.Running, _delay_1ms)
                .LoopRunWithStopStatus(CycleLoadStep.LoopUnloadWait, () => CheckRoutineEndStatus(_unloadRoutine), () => CheckRoutineStopStatus(_unloadRoutine))
                .LoopEnd(CycleLoadStep.LoopEnd, NullFun, _delay_2s)
                .End(CycleLoadStep.End, NullFun, _delay_1ms);
            return Runner.Status;
        }

        private bool CheckRoutineEndStatus(IRoutine routine)
        {
            return routine.Monitor() == RState.End;
        }

        private bool CheckRoutineStopStatus(IRoutine routine)
        {
            RState state =routine.Monitor();
            if(state==RState.Failed||state==RState.Timeout)
            {
                return true;
            }
            return false;
        }

        public RState Start(params object[] objs)
        {
            _cycle=(int)objs[0];
            return Runner.Start(Module, "Start cycle Load/Unload");
        }
    }
}