using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using MECF.Framework.Common.CommonData.PUF;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.TwinCat;
using CyberX8_Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CyberX8_RT.Devices.AXIS.GalilLipsel
{
   
    public class GalilRotationProfilePositionRoutine : RoutineBase, IRoutine
    {
        private enum ProfilePositionStep
        {
            WriteAcceleration,
            WriteDeceleration,
            WriteSpeed,
            WriteTargetPosition,
            StartMotion,
            Delay,
            CheckRunEnd,
            End
        }
        #region 常量 
        private const string PROFILE_VELOCITY = "ProfileVelocity";
        private const string PROFILE_ACCEL = "ProfileAccel";
        private const string PROFILE_DECEL = "ProfileDecel";
        private const string TARGET_POSITION = "TargetPosition";
        private const int MOTION_STOP_CODE = 1;
        #endregion
        #region 内部变量
        private JetAxisBase _axis;
        private int _profileVelocity = 0;
        private int _profileAcceleration = 0;
        private int _profileDeceleration = 0;
        private int _targetPosition;
        private bool _judgeTorqueLimit = false;
        #endregion
        public GalilRotationProfilePositionRoutine(string module,JetAxisBase axis) : base(module)
        {
            _axis = axis;
        }
        public void Abort()
        {
            Runner.Stop("Manual Abort");
        }
        public RState Monitor()
        {
            Runner.Run(ProfilePositionStep.WriteAcceleration, () => { return _axis.WriteAcceleration(_profileAcceleration); },_delay_1ms)
                .Run(ProfilePositionStep.WriteDeceleration, () => { return _axis.WriteDeceleration(_profileDeceleration); }, _delay_1ms)
                .Run(ProfilePositionStep.WriteSpeed, () => { return _axis.WriteSpeed(_profileVelocity); }, _delay_1ms)
                .Run(ProfilePositionStep.WriteTargetPosition, () => { return _axis.WriteAbsolutePosition(_targetPosition); }, _delay_1ms)
                .Run(ProfilePositionStep.StartMotion, () =>_axis.WriteStartMotion(), _delay_1ms)
                .Delay(ProfilePositionStep.Delay,500)
                .WaitWithStopCondition(ProfilePositionStep.CheckRunEnd,CheckRun,CheckRunStop)
                .End(ProfilePositionStep.End,NullFun,100);
            return Runner.Status;
        }
        /// 
        /// 检验是否正常运行
        /// 
        /// 
        private bool CheckRun()
        {
            bool isInTargetPosition = _axis.JudgeCurrentPositionIsInTargetPosition(_targetPosition);
            if (_judgeTorqueLimit)
            {
                if (!_axis.IsRun && isInTargetPosition)
                {
                    return true;
                }
                return false;
            }
            else
            {
                bool isTorqueOver = TorqueIsOverLimit();
                //过载同时掉电
                if (isTorqueOver && !_axis.IsSwitchOn)
                {
                    return true;
                }
                if (!_axis.IsRun && isInTargetPosition)
                {
                    return true;
                }
                return false;
            }
        }
        /// 
        /// Torque是否过载
        /// 
        /// 
        private bool TorqueIsOverLimit()
        {
            return !_axis.MotionData.TorqueLimited;
        }
        /// 
        /// 检验是否停止 
        /// 
        /// 
        private bool CheckRunStop()
        {
            //没有运动
            bool isStop = !_axis.IsRun&&!_axis.JudgeCurrentPositionIsInTargetPosition(_targetPosition);
            if(_judgeTorqueLimit)
            {
                if (isStop)
                {
                    ErrorMsg = "position is stop";
                    return true;
                }
            }
            return false;
        }
        public RState Start(params object[] objs)
        {
            _targetPosition = (int)objs[0];
            _profileVelocity = (int)objs[1];
            _profileAcceleration = (int)objs[2];
            _profileDeceleration = (int)objs[3];
            if(objs.Length>=5)
            {
                _judgeTorqueLimit = (bool)objs[4];
            }
            return Runner.Start(Module, "ProfilePosition");
        }
    }
}