#define ANIM_CROSS_FADE
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

// 单独一层动画
public class AnimatorLayerInfo
{
    public int layer;

    public int layerIndex { get { return (int)layer; } }

    public string name { get { return m_Animator.GetLayerName(layerIndex); } }

    public bool isBaseLayer { get { return layerIndex == 0; } }

    private Animator m_Animator;

    // 当前动作的animation data,如果是blendtree选第一个动作
    private AnimationData m_AnimationData;
    public AnimationData animationData
    {
        get
        {
            AnimatorClipInfo[] clipInfos = clipsInfo;
            if (clipInfos == null || clipInfos.Length == 0)
                return null;
            var clip = clipInfos[0]; //选第一个
            string folder = m_UnitAnimation.owner.folder;
            string name = clip.clip.name;
            if (m_AnimationData != null && m_AnimationData.animationName == name)
                return m_AnimationData;
            string path = folder + "AnimationData/" + name + ".asset" ; // 要注意这里使用名字区别的,因为最终每个角色的动画都会在一个目录下面
            m_AnimationData  = ResourceManager.Instance.LoadAsset<AnimationData>(path);
            return m_AnimationData;
        }
    }

	// 当前在播放的动作
	// 如果处于transition中,动作不变,切换完成后才会到下一个动作
	public AnimatorStateInfo stateInfo
    {
        get
        {
			AnimatorStateInfo stateInfo = m_Animator.GetCurrentAnimatorStateInfo(layerIndex);
			if (isInTransition) // 过渡中的动作认为当前动作是下一个动作
			{
				stateInfo = m_Animator.GetNextAnimatorStateInfo(layerIndex);
			}
		//	Debug.Assert(stateInfo.IsName(layerName + "." + m_CurrentState));
			return stateInfo;
		}
    }

    private int preStateHash = -1;

    // 当前正在播放和融合的片段信息
    public AnimatorClipInfo[] clipsInfo
    {
        get
        {
            AnimatorClipInfo[] clips = null;
            if (!isInTransition) 
            {
                clips = m_Animator.GetCurrentAnimatorClipInfo(layerIndex);
                if (clips.Length == 0)
                {
                    clips = m_Animator.GetNextAnimatorClipInfo(layerIndex);
                }
            }
            else // 过渡中的动作认为当前动作是下一个动作
            {
                clips = m_Animator.GetNextAnimatorClipInfo(layerIndex);
            }
            return clips;
        }
    }

	public AnimatorClipInfo clipInfo
	{
		get
		{
			return clipsInfo[0];
		}
	}

    public int stateHash
    {
        get
        {
            return stateInfo.shortNameHash;
        }
    }

    // 并非准确的播放时间,只是逻辑时间,因为动画会加速减速
    public float playbackTimeInSeconds
    {
        get
        {
            return playbackNormalizedTime * clipInfo.clip.length; 
        }
    }

    // 这个是真实世界的时间
    private float m_PlaybackRealTime;
    public float playbackRealTimeInSeconds
    {
        get
        {
            return m_PlaybackRealTime;
        }
    }

    // 播放进度百分比,[0-1],是逻辑上的,如果动画不是loop,那么播放完后normalizedTime是1
    public float playbackNormalizedTime
    {
        get
        {
            AnimatorStateInfo state = stateInfo;
            if (!state.loop && state.normalizedTime > 1)
                return 1;
            //if (state.IsName("Attack0"))
            //{
            //    Debug.Log("normalizedTime=" + state.normalizedTime);
            //    Debug.Log("playbackTimeInSeconds=" + state.normalizedTime * clipInfo.clip.length);
            //}
            return state.normalizedTime % 1f;
        }
    }

	public float playbackSpeed
	{
		get
		{
			return m_Animator.GetFloat("PlaybackSpeed" + layerIndex);
		}
		set
		{
			float v = Mathf.Clamp(value, 0, 10);
			m_Animator.SetFloat("PlaybackSpeed" + layerIndex, v);
		}
	}

	public float weight
    {
        get
        {
            return m_Animator.GetLayerWeight(layerIndex);
        }
    }

    public int nextStateHash
    {
        get
        {
            AnimatorStateInfo nextState = m_Animator.GetNextAnimatorStateInfo(layerIndex);
            int hash = nextState.shortNameHash; // 如果不在过渡中,hash是0
            return hash;
        }
    }

    public bool isInTransition
    {
        get
        {
            return m_Animator.IsInTransition(layerIndex);
        }
    }

	public bool applySpeedCurve { get; set; }

	UnitAnimation m_UnitAnimation;

    Coroutine m_CalcPlaybackTimeCoroutine;

	TimelineEventProxy m_TimelineEventProxy;

	public string m_CurrentState;

	public AnimatorLayerInfo(UnitAnimation unitAnimation, Animator animator, int layer)
    {
        this.m_UnitAnimation = unitAnimation;
        this.m_Animator = animator;
        this.layer = layer;
		m_CalcPlaybackTimeCoroutine = unitAnimation.StartCoroutine(CalcPlaybackRealTimeCoroutine());
		m_TimelineEventProxy = new TimelineEventProxy(unitAnimation.owner.transform, unitAnimation.owner);
		applySpeedCurve = true;
	}

	IEnumerator CalcPlaybackRealTimeCoroutine()
    {
        while (true)
        {
            if(preStateHash != stateHash)
            {
                m_PlaybackRealTime = 0;
            }
            m_PlaybackRealTime += Time.deltaTime;
            preStateHash = stateHash;
            yield return null; 
        }
    }

    public bool IsToggleOpen(EAnimationToogle toggle)
    {
        if (m_AnimationData == null)
            return false;
        return m_AnimationData.IsToggleOpen(toggle, playbackNormalizedTime);
    }

	public void OnUpdate()
	{
        // 执行事件
        m_TimelineEventProxy.ExecuteAnimationEvents(animationData, playbackTimeInSeconds * TimelineEventProxy.FPS);

        // 播放速度控制
        if (applySpeedCurve && animationData != null && animationData.speedCurve != null)
		{
			playbackSpeed = animationData.speedCurve.Evaluate(playbackNormalizedTime);
		}
	}

	public void OnCrossFade(string animState, float normalizedTransitionDuration, float normalizedTimeOffset, float normalizedTransitionTime )
	{
		m_CurrentState = animState;
		m_Animator.CrossFade(animState.ToString(), normalizedTransitionDuration, layerIndex, normalizedTimeOffset, normalizedTransitionTime);
        m_TimelineEventProxy.ResetPrevAnimationData();
    }

    public void OnPlay(string animState, float normalizedTime)
	{
		m_CurrentState = animState;
        m_Animator.Play(animState, layerIndex, normalizedTime);
        m_TimelineEventProxy.ResetPrevAnimationData();
    }

}

[DisallowMultipleComponent]
public class UnitAnimation : UnitComponent
{
    public AnimatorLayerInfo[] layers { get { return m_LayerInfo; } }
    protected AnimatorLayerInfo[] m_LayerInfo;

    public Animator animator { get { return m_Animator; } }
    protected Animator m_Animator;

    public virtual AnimatorLayerInfo baseLayer
    {
        get { return layers[0]; }
    }

    public bool isInTransition
    {
        get
        {
            return m_Animator.IsInTransition(0);
        }
    }

    public void Play(string animState, int layerIndex = 0, float normalizedTime = float.NegativeInfinity)
    {
        AnimatorLayerInfo layer = this.layers[layerIndex];
        if (layer == null)
            return;
        layer.OnPlay(animState, normalizedTime);

		UnitRootMotion rm = m_Owner.GetComponent<UnitRootMotion>();
		if(rm)
		{
			rm.OnAnimationChange();
		}
	}

    public void CrossFade(string animState, float normalizedTransitionDuration, int layerIndex = 0, float normalizedTimeOffset = float.NegativeInfinity, float normalizedTransitionTime = 0.0f)
    {
        AnimatorLayerInfo layer = this.layers[layerIndex];
        if (layer == null)
            return;
        layer.OnCrossFade(animState, normalizedTransitionDuration, normalizedTimeOffset, normalizedTransitionTime);

		UnitRootMotion rm = m_Owner.GetComponent<UnitRootMotion>();
		if (rm)
		{
			rm.OnAnimationChange();
		}
	}

}