using CMDType = ET.AnimatorEventType;
using AniType = Mono.AnimationData.AnimationType;
using UnityEngine;
using System.Text.RegularExpressions;

namespace ET.Client
{
    [Event(SceneType.Current)]
    public class AnimatorEventHandler : AEvent<EventType.PlayAnimatorEvent>
    {
        protected override async ETTask Run(Scene scene, EventType.PlayAnimatorEvent args)
        {
            var component = ModelViewComponent.Instance.GetChild<AnimatorComponent>(args.UnitId);
            if (component == null)
            {
                Log.Debug($"Not found AnimatorComponent of object{args.UnitId}");
                return;
            }
            if(args.CommandType == CMDType.Skill)
            {
                var m = Regex.Match(args.SkillName, "Skill(\\d+)");
                if (m.Success)
                {
                    int n = System.Convert.ToInt32(m.Groups[1].Value, 10);
                    if(n >=0 && AniType.SkillMax > AniType.Skill0 + n)
                    {
                        AnimatorCommand cmd = new AnimatorCommand((AniType)(AniType.Skill0 + n)) {
                            Duration = args.Duration,
                            Speed = args.Speed,
                            GroupId = args.GroupId,
                            Loop = args.Loop
                        };
                        component.AppendCommand(cmd);
                        return;
                    }
                }
                Log.Error($"Not support skill animation: {args.SkillName}");
            }
            else
            {
                AnimatorCommand cmd = args.CommandType switch
                {
                    AnimatorEventType.Idle => AnimatorComponent.CMDIdle,
                    AnimatorEventType.Run => AnimatorComponent.CMDRun,
                    AnimatorEventType.Dead => AnimatorComponent.CMDDead,
                    _ => AnimatorComponent.CMDIdle
                };
                component.AppendCommand(cmd);
            }
            
            await ETTask.CompletedTask;
        }
    }

    [FriendOf(typeof(AnimatorComponent))]
    public static class AnimatorComponentSystem
    {
        [ObjectSystem]
        public class AnimatorComponentAwakeSystem : AwakeSystem<AnimatorComponent, GameObject>
        {
            protected override void Awake(AnimatorComponent self, GameObject go)
            {
                self.GameObject = go;
                self.Awake();
            }
        }

        [ObjectSystem]
        public class AnimatorComponentUpdateSystem : UpdateSystem<AnimatorComponent>
        {
            protected override void Update(AnimatorComponent self)
            {
                self.Update();
            }
        }

        [ObjectSystem]
        public class AnimatorComponentDestroySystem : DestroySystem<AnimatorComponent>
        {
            protected override void Destroy(AnimatorComponent self)
            {
                self.AniData.Animancer.Stop();
                UnityEngine.Object.Destroy(self.GameObject);
            }
        }

        //===AnimatorComponent 扩展方法-------
        public static void AppendCommand(this AnimatorComponent self, AnimatorCommand cmd)
        {
            self.Commands.Add(cmd);
        }
        //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        public static void Awake(this AnimatorComponent self)
        {
            self.AniData = self.GameObject.GetComponent<Mono.AnimationData>();

            self.ExeCommand(AnimatorComponent.CMDIdle);
        }

        public static void Update(this AnimatorComponent self)
        {
            var cmd = self.FilterCmdList();
            if(cmd != null)
            {
                self.ExeCommand(cmd);
            }
        }

        //执行指令
        private static void ExeCommand(this AnimatorComponent self, AnimatorCommand cmd)
        {
            self.DoingCmd = (AnimatorCommand)cmd;
            self.AniData.PlayAnimation(cmd.Type);
        }

        //从指令队列中分析出当前需要执行的指令
        private static AnimatorCommand FilterCmdList(this AnimatorComponent self)
        {
            var cmds = self.Commands;
            if (cmds.Count <= 0)
            {
                return null;
            }

            /*var cmd = cmds[0];
            for(var i=1; i<cmds.Count; i++)
            {
                var next = cmds[i];
                if(next.Type == CMDType.StopRun && cmd.Type == CMDType.Run)
                {
                    cmd = AnimatorComponent.CMDIdle;
                }
                else if(next.Type == CMDType.StopSkill && cmd.Type >= CMDType.Skill0 && cmd.Type <= CMDType.Skill3)
                {
                    cmd = AnimatorComponent.CMDIdle;
                }
                else if(next.Type > cmd.Type && cmd.Type < CMDType.Skill0)
                {
                    cmd = next;
                }
            }*/
            var cmd = cmds[cmds.Count - 1];
            if(cmd.GroupId > 0)
            {
                int delIndex = -1;
                for(var i = cmds.Count -2; i >= 0; i--)
                {
                    if (cmds[i].GroupId != cmd.GroupId)
                    {
                        delIndex = i;
                        break;
                    }
                }
                if(delIndex >= 0)
                {
                    cmds.RemoveRange(0, delIndex + 1);
                }
            }
            else
            {
                cmds.Clear();
            }
            return cmd;
        }

    }
}