using Spine;
using Spine.Unity;
using System;
using UnityEngine;
using XGame;
using XGame.Framework.Components;
using XGame.Framework.Time;

namespace FL.Battle
{
    public enum ActionName : int
    {
        idle = 0,
        idle2,
        attack,
        skill,
    }
    public interface ISpineContext
    {
        SkeletonAnimation Skeleton { get; }
        ITimeModule Time { get; }
    }
    public class SpineComponent : Component<ISpineContext>
    {
        private ITimer _actionTimer;
        public override int Order => 0;

        protected override void OnDispose()
        {
            _actionTimer?.Cancel();
            _actionTimer = null;
        }
        public bool IsLoop(ActionName actionName)
        {
            switch (actionName)
            {
                case ActionName.idle:
                case ActionName.idle2:
                    return true;
                default: 
                    return false;
            }
        }
        public void Play(ActionName actionName, Action callback = null)
        {
            var skeleton = Context.Skeleton;
            if (skeleton == null)
                return;
            var isLoop = IsLoop(actionName);
            skeleton.loop = isLoop;
            skeleton.AnimationName = actionName.ToString();
            //var state = skeleton.AnimationState;
            //state.Tracks.Items[0].Animation.Duration
            if (_actionTimer != null)
            {
                Log.Warn($"Play actionName:{actionName}");
            }
            _actionTimer?.Cancel();
            if (!isLoop)
            { // 非循环动作才有回调
                SetSkeletonFill(Color.yellow, 0.7f);
                _actionTimer = Context.Time.AddDelayTimer(skeleton.GetDurationMS(), () =>
                {
                    SetSkeletonFill(Color.white, 0);
                    _actionTimer = null;
                    callback.SafeInvoke();
                });
            }
            //state.Complete += (_) =>
            //{
            //    callback?.Invoke();
            //};
        }
        private MaterialPropertyBlock _mpb = new MaterialPropertyBlock();
        /// <summary>
        /// 设置spine的自定义颜色
        /// http://zh.esotericsoftware.com/spine-unity
        /// </summary>
        /// <param name="color"></param>
        /// <param name="phase"></param>
        private void SetSkeletonFill(Color color, float phase)
        {
            var renderer = Context.Skeleton.GetComponent<MeshRenderer>();
            if (renderer.sharedMaterial.shader.name != "Spine/Skeleton Fill")
            { // 该shader可自定义颜色叠加(color overlay)的Unlit 透明着色器. 不写 z-buffer. FillColor 决定叠加颜色, FillPhase 决定叠加强度.
                return;
            }
            Log.Debug($"SetSkeletonFill color:{color} phase:{phase} Frame:{Time.frameCount}");
            _mpb.SetColor("_FillColor", color); // "_FillColor" is a named property on the used shader.
            _mpb.SetFloat("_FillPhase", phase); // "_FillPhase" is another named property on the used shader.
            renderer.SetPropertyBlock(_mpb);
        }

        //private void OnCompleted(TrackEntry trackEntry)
        //{
        //}
    }
}
