using System;
using System.Collections.Generic;
using UnityEngine;
using XGame;
using XGame.Database;
using XGame.Framework.Components;
using XGame.Framework.Interfaces;
using XGame.Framework.Time;

namespace FL.Battle.Components
{
    public interface IAnimatorContext
    {
        Animator Animator { get; }
        ITimeModule Time { get; }
    }
    public class AnimatorComponent : Component<IAnimatorContext>, IAnimator, IReset
    {
        /// <summary>
        /// Animator参数名
        /// int类型，数值参考EActionName
        /// </summary>
        private string STATE_VAL = "StateVal";
        private ITimer _actionTimer;
        /// <summary>
        /// 触发器的定时器
        /// </summary>
        private ITimer _triggerTimer;
        private Dictionary<EAnimationName, AnimationClip> _nameToClipMap;
        private float _baseSpeed = 1;



        protected override void OnEnable(object intent)
        {
            _baseSpeed = Context.Animator.speed;
            RefreshClips();
        }
        protected override void OnDisable()
        {
            _nameToClipMap?.Clear();
            Context.Animator.speed = _baseSpeed;
            ClearTimers();
        }
        protected override void OnDispose()
        {
            ClearTimers();
        }
        private void ClearTimers()
        {
            _actionTimer?.Cancel();
            _actionTimer = null;
            _triggerTimer?.Cancel();
            _triggerTimer = null;
        }
        public void Play(EAnimationName aniName)
        {
            Play(new AnimationPlayArgs { aniName = aniName });
        }
        public void Play(AnimationPlayArgs args)
        {
            var animator = Context.Animator;
            if (!_nameToClipMap.TryGetValue(args.aniName, out var clip))
            {
                Log.Error($"找不到动作配置. Animator:{animator.name} ActionName:{args.aniName}");
                return;
            }
            //if (_actionTimer != null)
            //{
            //    Log.Debug($"Animator Name:{animator.name} Now:{animator.GetInteger(STATE_VAL)} Next:{args.aniName}");
            //}
            animator.SetInteger(STATE_VAL, (int)args.aniName);
            ClearTimers();
            var duration = Mathf.CeilToInt(clip.length * 1000);
            if (args.onTrigger != null && args.triggerFrame > 0 && args.triggerFrame < duration)
            {
                _triggerTimer = Context.Time.AddDelayTimer(args.triggerFrame, () =>
                {
                    _triggerTimer = null;
                    args.onTrigger.SafeInvoke();
                });
            }
            if (!clip.isLooping)
            { // 非循环动作才有回调
                //Log.Debug($"Animator Start name:{args.aniName} clip:{clip.name} duration:{duration} time:{Time.realtimeSinceStartup} rotation:{animator.transform.localRotation}");
                _actionTimer = Context.Time.AddDelayTimer(duration, () =>
                {
                    //Log.Debug($"Animator End name:{args.aniName} clip:{clip.name} duration:{duration} time:{Time.realtimeSinceStartup} rotation:{animator.transform.localRotation}");
                    _actionTimer = null;
                    animator.SetInteger(STATE_VAL, (int)args.fallback);
                    args.onCompleted.SafeInvoke();
                });
            }
            //state.Complete += (_) =>
            //{
            //    callback?.Invoke();
            //};
        }

        private void RefreshClips()
        {
            if (_nameToClipMap == null)
            {
                _nameToClipMap = new Dictionary<EAnimationName, AnimationClip>();
            }
            var controller = Context.Animator.runtimeAnimatorController;
            if (controller != null && controller.animationClips != null)
            {
                foreach (var clip in controller.animationClips)
                {
                    if (Enum.TryParse<EAnimationName>(clip.name, out var actionName))
                    {
                        _nameToClipMap.Add(actionName, clip);
                    }
                    else
                    {
                        Log.Error($"AnimationClip 命名错误. Animator:{Context.Animator.name} Clip:{clip.name}");
                    }
                }
            }
            //foreach (var parameter in Context.Animator.parameters)
            //{
            //    var id = parameter.nameHash;
            //    Context.Animator.SetBool(id, true);
            //}
        }

        void IReset.Reset()
        {
            ClearTimers();
        }
    }
}
