using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using CyberX8_Core;
using CyberX8_RT.Devices.AXIS;
using CyberX8_RT.Devices.SRD;
using MECF.Framework.Common.Routine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using static CyberX8_RT.Modules.SRD.UnloadingStateMachine;

namespace CyberX8_RT.Modules.SRD
{
    public class SRDUnloadRoutine : RoutineBase, IRoutine
    {
        private enum UnloadStep
        {
            Unloading_Start,
            Unloading_CheckArmHomed,
            Unloading_CheckRotationHomed,
            Unloading_WaferPresent,
            Unloading_OpenDoor,
            Unloading_CheckDoorOpened,
            Unloading_ReleaseChuckVacuum,
            Unloading_CheckVacuum,
            Test,
            End
        }
        #region 常量 
        /// <summary>
        /// Arm Home最大retry次数
        /// </summary>
        private const int MAX_ARM_HOME_RETRIES = 3;
        /// <summary>
        /// Rotation Home最大retry次数
        /// </summary>
        private const int MAX_ROTATION_HOME_RETRIES = 3;
        /// <summary>
        /// 旋转增加时长
        /// </summary>
        private const int ROTATION_PLUS_TIME = 10;
        #endregion

        #region 内部变量
        /// <summary>
        /// SRD Common
        /// </summary>
        private SrdCommonDevice _srdCommon;
        /// <summary>
        /// Arm Axis
        /// </summary>
        private JetAxisBase _armAxis;
        /// <summary>
        /// Rotation Axis
        /// </summary>
        private JetAxisBase _rotationAxis;
        /// <summary>
        /// Arm重试次数
        /// </summary>
        private int _armRetryTimes = 0;
        /// <summary>
        /// Rotation重试次数
        /// </summary>
        private int _rotationRetryTimes = 0;
        #endregion
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="module"></param>
        public SRDUnloadRoutine(string module) : base(module)
        {
        }

        /// <summary>
        /// 中止
        /// </summary>
        public void Abort()
        {
            Runner.Stop("SRD Unloading Abort");
        }
        /// <summary>
        /// 监控
        /// </summary>
        /// <returns></returns>
        public RState Monitor()
        {
            Runner.Run(UnloadStep.Unloading_Start, NullFun, _delay_1ms)
                .WaitWithStopCondition(UnloadStep.Unloading_CheckArmHomed, CheckArmEndStatus, CheckArmStopStatus)
                .WaitWithStopCondition(UnloadStep.Unloading_CheckRotationHomed, CheckRotationEndStatus, CheckRotationStopStatus)
                .Run(UnloadStep.Unloading_WaferPresent, CheckWaferPresent, _delay_1ms)
                .Run(UnloadingState.Unloading_OpenDoor, OpenDoor, _delay_1ms)
                .WaitWithStopCondition(UnloadingState.Unloading_CheckDoorOpened, CheckDoorOpenedEndStatus, CheckDoorOpenedStopStatus)
                .Run(UnloadingState.Unloading_ReleaseChuckVacuum, ReleaseChuckVacuum, _delay_1ms)
                .WaitWithStopCondition(UnloadStep.Unloading_CheckVacuum, CheckReleaseChuckEndStatus, CheckReleaseChuckStopStatus)
                .End(UnloadStep.End, NullFun, _delay_1ms);
            return Runner.Status;
        }

        /// <summary>
        /// 检验Arm home结束状态
        /// </summary>
        /// <returns></returns>
        private bool CheckArmEndStatus()
        {
            if (_armAxis.IsHomed && _armAxis.Status == RState.End)
            {
                _armRetryTimes = 0;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 检验Arm停止状态
        /// </summary>
        /// <returns></returns>
        private bool CheckArmStopStatus()
        {
            if (_armAxis.Status == RState.Failed || _armAxis.Status == RState.Timeout)
            {
                if (_armRetryTimes < MAX_ARM_HOME_RETRIES)
                {
                    _armAxis.Home(false);
                    _armRetryTimes++;
                }
                else
                {
                    NotifyError(eEvent.ERR_SRD, $"Arm Home Retry Home {_armRetryTimes + 1} times is over {MAX_ARM_HOME_RETRIES}", 0);
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 检验Rotation home结束状态
        /// </summary>
        /// <returns></returns>
        private bool CheckRotationEndStatus()
        {
            if (_rotationAxis.IsHomed && _rotationAxis.Status == RState.End)
            {
                _rotationRetryTimes = 0;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 检验Rotation停止状态
        /// </summary>
        /// <returns></returns>
        private bool CheckRotationStopStatus()
        {
            if (_rotationAxis.Status == RState.Failed || _rotationAxis.Status == RState.Timeout)
            {
                if (_rotationRetryTimes < MAX_ROTATION_HOME_RETRIES)
                {
                    _rotationAxis.Home(false);
                    _rotationRetryTimes++;
                }
                else
                {
                    NotifyError(eEvent.ERR_SRD, $"Rotation Home Retry Home {_rotationRetryTimes + 1} times is over {MAX_ROTATION_HOME_RETRIES}", 0);
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// Check Wafer Present
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private bool CheckWaferPresent()
        {
            if (_srdCommon.IsWaferPresence)
            {
                if (_srdCommon.WaferPresence != "WellPlaced")
                {
                    NotifyError(eEvent.ERR_SRD, "Wafer Presence is not WellPlaced",0);
                    return false;
                }
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_SRD, Module, "CheckWaferPresent has been ignored");

            }
            return true;
        }
        /// <summary>
        /// Open Door
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private bool OpenDoor()
        {
            return _srdCommon.DoorOpenAction("", null);
        }
        /// <summary>
        /// 检验DoorOpened
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private bool CheckDoorOpenedEndStatus()
        {
            bool result = _srdCommon.Status == RState.End;
            if (result)
            {
                if (_srdCommon.CommonData.DoorOpened && !_srdCommon.CommonData.DoorClosed)
                {
                    return true;
                }
                else
                {
                    NotifyError(eEvent.ERR_SRD, $"Opened {_srdCommon.CommonData.DoorOpened}&&Closed {_srdCommon.CommonData.DoorClosed}", 0);
                    return false;
                }
            }
            return false;
        }
        /// <summary>
        /// 检验Door
        /// </summary>
        /// <returns></returns>
        private bool CheckDoorOpenedStopStatus()
        {
            return _srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout;
        }
        /// <summary>
        /// 关闭Chuck Vacuum,并检查Vacuum Level
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private bool ReleaseChuckVacuum()
        {
            return _srdCommon.ChuckVacuumOffAction("", null);
        }
        /// <summary>
        /// 检验Release Chuck结束状态
        /// </summary>
        /// <returns></returns>
        private bool CheckReleaseChuckEndStatus()
        {
            return _srdCommon.Status==RState.End;
        }
        /// <summary>
        /// 检验Release Chuck停止状态
        /// </summary>
        /// <returns></returns>
        private bool CheckReleaseChuckStopStatus()
        {
            return _srdCommon.Status == RState.Failed||_srdCommon.Status==RState.Timeout;
        }
        /// <summary>
        /// 启动
        /// </summary>
        /// <param name="objs"></param>
        /// <returns></returns>
        public RState Start(params object[] objs)
        {
            _armAxis = DEVICE.GetDevice<JetAxisBase>($"{Module}.Arm");
            _rotationAxis = DEVICE.GetDevice<JetAxisBase>($"{Module}.Rotation");
            _srdCommon = DEVICE.GetDevice<SrdCommonDevice>($"{Module}.Common");
            return Runner.Start(Module, "Start Unload Wafer");
        }
    }
}