﻿using UnityEngine;

namespace JLGames.RocketDriver.Actions.Animatorx
{
    public static class AnimatorUtils
    {
        /// <summary>
        /// Find Clip
        /// 查找剪辑
        /// </summary>
        /// <param name="anim"></param>
        /// <param name="clipName"></param>
        /// <returns></returns>
        public static AnimationClip FindClip(this Animator anim, string clipName)
        {
            if (null == anim || string.IsNullOrEmpty(clipName)) return null;
            var clips = anim.runtimeAnimatorController.animationClips;
            if (null == clips || clips.Length == 0) return null;
            for (var index = 0; index < clips.Length; index++)
            {
                if (clips[index].name == clipName) return clips[index];
            }

            return null;
        }

        /// <summary>
        /// Play animation with validation
        /// 带验证的动画播放切换
        /// </summary>
        /// <param name="anim"></param>
        /// <param name="state"></param>
        public static void PlayState(this Animator anim, string state)
        {
            if (string.IsNullOrEmpty(state)) return;
            anim.Play(state);
        }

        /// <summary>
        /// Check the animation name currently playing
        /// 检查当前播放中的动画名
        /// </summary>
        /// <param name="anim"></param>
        /// <param name="stateName"></param>
        /// <param name="layerIndex"></param>
        /// <returns></returns>
        public static bool CheckCurrentState(this Animator anim, string stateName, int layerIndex = 0)
        {
            return anim.GetCurrentAnimatorStateInfo(layerIndex).IsName(stateName);
        }

        /// <summary>
        /// Get the animation name currently playing
        /// 获取当前播放中的动画名
        /// </summary>
        /// <param name="anim"></param>
        /// <param name="layerIndex"></param>
        /// <returns></returns>
        public static string GetCurrentStateName(this Animator anim, int layerIndex = 0)
        {
            return anim.GetCurrentAnimatorClipInfo(layerIndex)[0].clip.name; // Why return a array? When return multiple elements?
        }

        /// <summary>
        /// Play animation on display object
        /// 在显示对象上播放动画
        /// </summary>
        /// <param name="view"></param>
        /// <param name="controller"></param>
        /// <param name="state"></param>
        public static void PlayAnimation(GameObject view, RuntimeAnimatorController controller, string state = null)
        {
            if (null == view) return;
            var anim = TryAddAnimator(view);
            if (null == anim.runtimeAnimatorController && null == controller) return;
            if (null != controller)
            {
                anim.runtimeAnimatorController = controller;
            }

            anim.PlayState(state);
        }

        /// <summary>
        /// Play animation on Animator object
        /// 在Animator上执行动画
        /// </summary>
        /// <param name="anim"></param>
        /// <param name="controller"></param>
        /// <param name="state"></param>
        public static void PlayAnimation(Animator anim, RuntimeAnimatorController controller, string state = null)
        {
            if (null == anim) return;
            if (null == anim.runtimeAnimatorController && null == controller) return;
            if (null != controller)
            {
                anim.runtimeAnimatorController = controller;
            }

            anim.PlayState(state);
        }

        /// <summary>
        /// Try to add an Animator component to the display object
        /// 尝试给显示对象添加Animator组件
        /// </summary>
        /// <param name="view"></param>
        /// <returns>The newly added or existing component(新增或已存在的组件)</returns>
        public static Animator TryAddAnimator(GameObject view)
        {
            if (null == view) return null;
            var anim = view.GetComponent<Animator>();
            if (null == anim)
            {
                anim = view.AddComponent<Animator>();
            }

            return anim;
        }

#if UNITY_EDITOR
        /// <summary>
        /// Print all clip names
        /// 打印全部剪辑名称
        /// </summary>
        /// <param name="anim"></param>
        public static void PrintClipNames(Animator anim)
        {
            var clips = anim.runtimeAnimatorController.animationClips;
            for (var index = 0; index < clips.Length; index++)
            {
                Debug.Log($"AnimatorObject[{anim.gameObject.name}][{index}].name=[{clips[index].name}]");
            }
        }
#endif
    }
}