using Aitex.Core.RT.Device;
using Aitex.Core.RT.Fsm;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Utilities;
using MECF.Framework.Common.Beckhoff.AxisProvider;
using MECF.Framework.Common.Utilities;
using CyberX8_Core;
using CyberX8_RT.Devices.AXIS;
using CyberX8_RT.Devices.SRD;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace CyberX8_RT.Modules.SRD
{
    internal class UnloadingStateMachine : Entity, IEntity
    {
        #region 常量 
        /// 
        /// Arm Home最大retry次数
        /// 
        private const int MAX_ARM_HOME_RETRIES = 3;
        /// 
        /// Rotation Home最大retry次数
        /// 
        private const int MAX_ROTATION_HOME_RETRIES = 3;
        /// 
        /// 旋转增加时长
        /// 
        private const int ROTATION_PLUS_TIME = 10;
        #endregion
        #region 内部变量
        /// 
        /// 模块名称
        /// 
        private string _module;
        /// 
        /// SRD Common
        /// 
        private SrdCommonDevice _srdCommon;
        /// 
        /// Arm Axis
        /// 
        private JetAxisBase _armAxis;
        /// 
        /// Rotation Axis
        /// 
        private JetAxisBase _rotationAxis;
        /// 
        /// Arm重试次数
        /// 
        private int _armRetryTimes = 0;
        /// 
        /// Rotation重试次数
        /// 
        private int _rotationRetryTimes = 0;
        /// 
        /// ARM正在执行Home
        /// 
        private bool _armHoming = false;
        /// 
        /// Rotation正在执行Home
        /// 
        private bool _rotationHoming = false;
        #endregion
        #region 属性
        /// 
        /// 状态
        /// 
        public string State { get { return ((UnloadingState)fsm.State).ToString(); } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public UnloadingStateMachine(string module)
        {
            _module = module;
            this.fsm = new StateMachine($"{module}_UnloadingStateMachine", (int)UnloadingState.Unloading_Complete, 10);
            fsm.EnableRepeatedMsg(true);
            
            AnyStateTransition(UnloadingMsg.Init, EnterUnloadingStart, UnloadingState.Unloading_Start);
            AnyStateTransition(UnloadingMsg.Error, EnterError, UnloadingState.Error);
            //Transition(UnloadingState.Unloading_Complete, UnloadingMsg.Unloading_Start, EnterUnloadingStart, UnloadingState.Unloading_Start);
            Transition(UnloadingState.Unloading_Start, UnloadingMsg.Unloading_Start, UnloadingCheckStatus, UnloadingState.Unloading_CheckRotationStopped);
            Transition(UnloadingState.Unloading_CheckRotationStopped, FSM_MSG.TIMER, CheckRotationStopped, UnloadingState.Unloading_WaferPresent);
            Transition(UnloadingState.Unloading_WaferPresent, FSM_MSG.TIMER, CheckWaferPresent, UnloadingState.Unloading_OpenDoor);
            Transition(UnloadingState.Unloading_OpenDoor, FSM_MSG.TIMER, OpenDoor, UnloadingState.Unloading_CheckDoorOpened);
            Transition(UnloadingState.Unloading_CheckDoorOpened, FSM_MSG.TIMER, CheckDoorOpened, UnloadingState.Unloading_ReleaseChuckVacuum);
            Transition(UnloadingState.Unloading_ReleaseChuckVacuum, FSM_MSG.TIMER, ReleaseChuckVacuum, UnloadingState.Unloading_CheckVacuum);
            Transition(UnloadingState.Unloading_CheckVacuum, FSM_MSG.TIMER, CheckVacuum, UnloadingState.Unloading_Complete);
            EnumLoop.ForEach((item) => { fsm.MapState((int)item, item.ToString()); });
            EnumLoop.ForEach((item) => { fsm.MapMessage((int)item, item.ToString()); });
        }
        /// 
        /// Enter Error
        /// 
        /// 
        /// 
        private bool EnterError(object param)
        {
            
            return true;
        }
        /// 
        /// Enter Unloading_Start
        /// 
        /// 
        /// 
        private bool EnterUnloadingStart(object param)
        {            
            return true;
        }
        #region 状态方法
        /// 
        /// 启动
        /// 
        /// 
        /// 
        private bool UnloadingCheckStatus(object param)
        {
            
            _armAxis = DEVICE.GetDevice($"{_module}.Arm");            
            _rotationAxis = DEVICE.GetDevice($"{_module}.Rotation");          
            _srdCommon = DEVICE.GetDevice($"{_module}.Common");
            return true;
        }
        /// 
        /// 检查Rotation与Arm是否home
        /// 
        /// 
        /// 
        private bool CheckRotationStopped(object param)
        {
            CheckArmHome();
            CheckRotationHome();
            return _srdCommon.Status == RState.End;
        }
        /// 
        /// 检验Arm home,发现失败则重试
        /// 
        /// 
        /// 
        private bool CheckArmHome()
        {
            if (_armAxis.IsHomed)
            {
                return true;
            }
            else
            {
                if (_armRetryTimes < MAX_ARM_HOME_RETRIES)
                {
                    if (!_armHoming)
                    {
                        LOG.WriteLog(eEvent.INFO_SRD, _module, $"Arm Home Retry Home {_armRetryTimes + 1} times");
                        bool result = _armAxis.Home(false);
                        if (result)
                        {
                            _armHoming = true;
                        }
                        _armRetryTimes++;
                        return false;
                    }
                    else
                    {
                        if (_armAxis.IsHomed && _armAxis.Status == RState.End)
                        {
                            _armRetryTimes = 0;
                            _armHoming = false;
                            return true;
                        }
                        return false;
                    }
                }
                else
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, $"Arm Home Retry Home {_armRetryTimes + 1} times is over {MAX_ARM_HOME_RETRIES}");
                    PostMsg(UnloadingMsg.Error);
                    return false;
                }
            }
        }
        /// 
        /// 检验Rotation home,发现失败则重试
        /// 
        /// 
        /// 
        private bool CheckRotationHome()
        {
            if (_rotationAxis.IsHomed)
            {
                return true;
            }
            else
            {
                if (_rotationRetryTimes < MAX_ROTATION_HOME_RETRIES)
                {
                    if (!_rotationHoming)
                    {
                        LOG.WriteLog(eEvent.INFO_SRD, _module, $"Rotation Home Retry Home {_rotationRetryTimes + 1} times");
                        bool result = _rotationAxis.Home(false);
                        if (result)
                        {
                            _rotationHoming = true;
                        }
                        _rotationRetryTimes++;
                        return false;
                    }
                    else
                    {
                        if (_rotationAxis.IsHomed && _rotationAxis.Status == RState.End)
                        {
                            _rotationRetryTimes = 0;
                            _rotationHoming = false;
                            return true;
                        }
                        return false;
                    }
                }
                else
                {
                    LOG.WriteLog(eEvent.ERR_SRD, _module, $"Rotation Home Retry Home {_rotationRetryTimes + 1} times is over {MAX_ROTATION_HOME_RETRIES}");
                    PostMsg(UnloadingMsg.Error);
                    return false;
                }
            }
        }
        /// 
        /// Check Wafer Present
        /// 
        /// 
        /// 
        private bool CheckWaferPresent(object param)
        {
            if (_srdCommon.IsWaferPresence)
            {
                if (_srdCommon.WaferPresence != "WellPlaced")
                {
                    PostMsg(UnloadingMsg.Error);
                    LOG.WriteLog(eEvent.ERR_SRD, _module, "Wafer Presence is not WellPlaced");
                    return false;
                }
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_SRD, _module, "CheckWaferPresent has been ignored");
                
            }
            return true;
        }
        /// 
        /// Open Door
        /// 
        /// 
        /// 
        private bool OpenDoor(object param)
        {
            bool result = _srdCommon.DoorOpenAction("", null);
            if (!result)
            {
                PostMsg(UnloadingMsg.Error);
            }
            return result;
        }
        /// 
        /// 检验DoorOpened
        /// 
        /// 
        /// 
        private bool CheckDoorOpened(object param)
        {
            if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
            {
                PostMsg(UnloadingMsg.Error);
                return false;
            }
            return _srdCommon.Status == RState.End && _srdCommon.CommonData.DoorOpened;
        }
        /// 
        /// 关闭Chuck Vacuum,并检查Vacuum Level
        /// 
        /// 
        /// 
        private bool ReleaseChuckVacuum(object param)
        {
            if (_srdCommon.IsWaferPresence)
            {
                bool result = _srdCommon.ChuckVacuumOffAction("", null);
                if (!result)
                {
                    PostMsg(UnloadingMsg.Error);
                }
                return result;
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_SRD, _module, "ReleaseChuckVacuum has been ignored");
                return true;
            }
        }
        /// 
        /// 检查真空状态
        /// 
        /// 
        /// 
        private bool CheckVacuum(object param)
        {
            if (_srdCommon.IsWaferPresence)
            {
                if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
                {
                    PostMsg(UnloadingMsg.Error);
                    return false;
                }
                bool result = _srdCommon.Status == RState.End && _srdCommon.CommonData.ChuckVacuum;
                return result;
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_SRD, _module, "CheckVacuum has been ignored");
                return true;
            }
            
        }
        #endregion
        /// 
        /// 停止 
        /// 
        public void Stop()
        {
            
            base.Terminate();
            
        }
        
        public bool Check(int msg, out string reason, params object[] args)
        {
            reason = "";
            return false;
        }
        #region State Msg枚举
        public enum UnloadingState
        {
            None,
            Error,
            Unloading_Start,
            Unloading_Complete,
            Unloading_CheckRotationStopped,
            Unloading_WaferPresent,
            Unloading_OpenDoor,
            Unloading_CheckDoorOpened,
            Unloading_ReleaseChuckVacuum,
            Unloading_CheckVacuum
            
        }
        public enum UnloadingMsg
        {
            Init,
            Error,
            Unloading_Start,
            Unloading_Complete,
            CheckRoationStopped,
            WaferPresent,
            OpenDoor,
            ReleaseChuckVacuum,
            Abort
        }
        #endregion
    }
}