/* 
 * 程序功能:
 * 设置手臂的行为    action
 * 设置手臂的帧序列  frameIndex
 */
using System;
using UnityEngine;
/// <summary>
/// 手臂动作帧
/// </summary>
public class ArmActionFrame : MonoBehaviour
{
    //动作类型
    public ActionType action = ActionType.RotateToTarget;
    //序列
    public int FrameIndex;
    //动作完成
    public Action OnFinished;
    //模型轴向错误
    public bool IsOpposite = false;
    //手臂长度偏移量
    public int ArmLenthOffset = 16;
    //x轴旋转的最大角度
    public float MaxRotateX = 0;
    public float MinRotateX = -84f;
    //臂长
    public float Maxlength = 15.8f;
    public float Minlength = 0.01634139f;
    //动作是否完成
    private bool IsFinished = true;
    //动作速度
    public float Speed = 20;
    //目标点
    private Vector3 targetPosition;
    //旋转的向量
    private Vector3 newDir;
    //旋转量
    private Quaternion quaternion;
    //根据距离旋转高度
    public int Distance = 20;
    #region 移动的变量
    //当前高度
    private ArmAction manager;
    private void Awake()
    {
        manager = GetComponentInParent<ArmAction>();
    }
    public float CurrentHeight
    {
        set
        {
            if (value >= Maxlength)
            {
                value = Maxlength;
                Finished();
            }
            if (value <= Minlength)
            {
                value = Minlength;
                Finished();
            }
            transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y, value);
#if UNITY_EDITOR
            Debug.DrawLine(manager.EndTrans.position, targetPosition, Color.yellow);
#endif
        }
        get { return transform.localPosition.z; }
    }
    #endregion
    /// <summary>
    /// 根据坐标行动作
    /// </summary>
    /// <param name="position">坐标</param>
    public void Init(Vector3 position, bool isRest)
    {
        //停止当前动作
        Stop();
        //设置目标点,初始化信息
        targetPosition = position;
        isRestPosition = isRest;
        switch (action)
        {
            case ActionType.RotateToTarget:
                InitAllDir();
                break;
            case ActionType.RotateToTargetVertacal:
                InitVetacalDir();
                break;
            case ActionType.RotateToTargetHorizatal:
                InitHorizatalDir();
                break;
            case ActionType.TranlateToForward:
                InitTarnslateToForward();
                break;
            case ActionType.RotateVertacalWithDistance:
                InitVetacalDistance();
                break;
        }
        //动作开始
        IsFinished = false;
    }

    private Vector3 resetPosition;
    private Quaternion resetRotation;
    private bool isRestPosition = false;
    private void Start()
    {
        //记录初始臂长
        //resetPosition = transform.position;
        //记录初始水平角度
        resetRotation = transform.localRotation;
    }
    public void Play(Vector3 position)
    {
        Init(position, false);
    }
    public void Play()
    {
        Init(manager.targetPosition, false);
    }
    /// <summary>
    /// 复位
    /// </summary>
    public void ResetArm()
    {
        Init(Vector3.zero, true);
    }
    /// <summary>
    /// 停止动作
    /// </summary>
    public void Stop()
    {
        IsFinished = true;
    }
    /// <summary>
    /// 动作完成,执行下一个动作
    /// </summary>
    public void Finished()
    {
        Stop();
        if (OnFinished != null)
        {
            OnFinished();
        }
    }
    /// <summary>
    /// 帧更新
    /// </summary>
    void Update()
    {
        if (!IsFinished)
        {
            Move();
        }
    }
    /// <summary>
    /// 
    /// </summary>
    private void Move()
    {
        if (action == ActionType.TranlateToForward)
        {
            //臂长
            float d2E = Mathf.FloorToInt(Vector3.Distance(manager.EndTrans.position, manager.StartTrans.position)) + ArmLenthOffset;
            float d2T = Mathf.FloorToInt(Vector3.Distance(manager.StartTrans.position, targetPosition));//臂底端到目标的距离   
            if (d2E < d2T)
            {
                CurrentHeight += Time.deltaTime * Speed;
            }
            else if (d2E > d2T)
            {
                CurrentHeight -= Time.deltaTime * Speed;
            }
            else
            {
                Finished();
            }
        }
        else if (action == ActionType.RotateVertacalWithDistance)
        {
            //复位
            if (isRestPosition)
            {
                transform.localRotation = Quaternion.RotateTowards(transform.localRotation, quaternion, Time.deltaTime * Speed * 2);
                if (transform.localRotation == quaternion)
                {
                    Finished();
                }
            }
            else
            {
                //检查尾端与目标点距离
                float distance = Mathf.Round(Vector3.Distance(manager.EndTrans.position, targetPosition));
                float targetDistance = ArmLenthOffset + Distance;

                Debug.Log(string.Format("距离:{0}-目标距离:{1}", distance, targetDistance));
                //距离小的时候抬高
                if (distance < targetDistance)
                {
                    Raise(Time.deltaTime * Speed * 2);
                    //Debug.Log("需要抬高");
                }
                else if (distance > targetDistance)
                {
                    Decline(Time.deltaTime * Speed * 2);
                    //Debug.Log("需要降低");
                }
                float x = CheckValue(transform.localEulerAngles.x);
                if (distance == targetDistance || x == MinRotateX || x == MaxRotateX)
                {
                    Finished();
                }
            }
        }
        else
        {
            //复位
            if (isRestPosition)
            {
                transform.localRotation = Quaternion.RotateTowards(transform.localRotation, quaternion, Time.deltaTime * Speed * 2);
                if (transform.localRotation == quaternion)
                {
                    Finished();
                }
            }
            else
            {
                transform.rotation = Quaternion.RotateTowards(transform.rotation, quaternion, Time.deltaTime * Speed * 2);
                float x = CheckValue(transform.localEulerAngles.x);
                if (x < MinRotateX && !IsOpposite)
                {
                    transform.localEulerAngles = new Vector3(MinRotateX, transform.localEulerAngles.y, transform.localEulerAngles.z);
                    Finished();
                    return;
                }
                if (x > MaxRotateX & !IsOpposite)
                {
                    transform.localEulerAngles = new Vector3(MaxRotateX, transform.localEulerAngles.y, transform.localEulerAngles.z);
                    Finished();
                    return;
                }
                if (transform.rotation == quaternion)
                {

                    Finished();
                }
            }
            //Debug
#if UNITY_EDITOR
            switch (action)
            {
                case ActionType.RotateToTarget:
                    Debug.DrawRay(transform.position, newDir, Color.blue);
                    break;
                case ActionType.RotateToTargetVertacal:
                    Debug.DrawRay(transform.position, newDir, Color.green);
                    break;
                case ActionType.RotateToTargetHorizatal:
                    Debug.DrawRay(transform.position, newDir, Color.red);
                    break;
            }
#endif
        }
    }
    /// <summary>
    /// 向下降低Bi1
    /// </summary>
    /// <param name="speed"></param>
    public void Decline(float speed)
    {
        float x = transform.localEulerAngles.x;
        float y = transform.localEulerAngles.y;
        x = CheckValue(x);
        x += speed;
        x = Mathf.Clamp(x, MinRotateX, MaxRotateX);//模型穿插,调整模型预设后,这里参数也跟着修改。
        transform.localEulerAngles = new Vector3(x, y, 0);
    }
    /// <summary>
    /// 向上抬起Bi1
    /// </summary>
    /// <param name="speed"></param>
    public void Raise(float speed)
    {
        float x = transform.localEulerAngles.x;
        float y = transform.localEulerAngles.y;
        x = CheckValue(x);
        x -= speed;
        x = Mathf.Clamp(x, MinRotateX, MaxRotateX);//模型穿插,调整模型预设后,这里参数也跟着修改。
        transform.localEulerAngles = new Vector3(x, y, 0);
    }
    /// <summary>
    /// 初始化所有方位的旋转量
    /// </summary>
    private void InitAllDir()
    {
        if (isRestPosition)
        {
            quaternion = resetRotation;
        }
        else
        {
            var targetDir = targetPosition - transform.position;
            var forward = transform.forward;
            newDir = targetDir;
            quaternion = Quaternion.LookRotation(newDir);
        }
    }
    /// <summary>
    /// 初始化垂直方向旋转量
    /// </summary>
    private void InitVetacalDir()
    {

        if (isRestPosition)
        {
            quaternion = resetRotation;
        }
        else
        {
            Vector3 hightOffSetPosition = new Vector3(targetPosition.x, targetPosition.y, targetPosition.z);
            Vector3 targetDir = hightOffSetPosition - transform.position;
            newDir = targetDir - Vector3.Dot(targetDir, transform.right) * transform.right;
            if (IsOpposite)
            {
                float temp = Vector3.Angle(newDir, transform.forward);
                if (temp > 90f)
                {
                    quaternion = Quaternion.LookRotation(-newDir, transform.up);
                }
                else
                {
                    quaternion = Quaternion.LookRotation(-newDir, -transform.up);
                }
            }
            else
            {
                quaternion = Quaternion.LookRotation(newDir, transform.up);
            }
        }
    }
    public void InitVetacalDistance()
    {
        if (isRestPosition)
        {
            quaternion = resetRotation;
        }
    }
    /// <summary>
    /// 初始化水平方向旋转量
    /// </summary>
    private void InitHorizatalDir()
    {
        if (isRestPosition)
        {
            quaternion = resetRotation;
        }
        else
        {
            // 底臂part1到目标位置的向量
            Vector3 targetDir = targetPosition - transform.position;
            //【BiTar在底臂forward方向上的分向量】 = 【BiTar向量】 - 【BiTar在底臂up方向上的分向量】
            newDir = targetDir - Vector3.Dot(targetDir, transform.up) * transform.up;
            //由BiTar的【forward分向量】和【up分向量组成的】 旋转量Quaternion
            if (IsOpposite)
            {
                float temp = Vector3.Angle(newDir, transform.forward);
                if (temp > 90f)
                {
                    quaternion = Quaternion.LookRotation(-newDir, transform.up);
                }
                else
                {
                    quaternion = Quaternion.LookRotation(-newDir, -transform.up);
                }
            }
            else
            {
                quaternion = Quaternion.LookRotation(newDir, transform.up);
            }
        }
    }
    /// <summary>
    /// 初始化移动信息
    /// </summary>
    private void InitTarnslateToForward()
    {
        if (isRestPosition)
        {
            targetPosition = transform.position;
        }
    }
    /// <summary>
    /// 验证旋转角度
    /// </summary>
    /// <param name="x"></param>
    /// <returns></returns>
    protected float CheckValue(float x)
    {
        if (x >= 180 && x <= 360)
        {
            x = x - 360;
        }
        return x;
    }
}
/// <summary>
/// 动作类型
/// </summary>
public enum ActionType
{
    /// <summary>
    /// 朝向举臂
    /// </summary>
    RotateToTarget,
    /// <summary>
    /// 垂直举臂
    /// </summary>
    RotateToTargetVertacal,
    /// <summary>
    /// 水平举臂
    /// </summary>
    RotateToTargetHorizatal,
    /// <summary>
    /// 伸缩举臂
    /// </summary>
    TranlateToForward,
    /// <summary>
    /// 根据距离旋转高度
    /// </summary>
    RotateVertacalWithDistance
}