using CMDType = ET.AnimatorEventType;
using AniType = Mono.AnimationData.AnimationType;
using UnityEngine;
using System.Text.RegularExpressions;
using ET.EventType;
using Sirenix.Utilities;
using CommonAI.Zone;
using FairyGUI;

namespace ET.Client
{
    [Event(SceneType.Current)]
    [FriendOf(typeof(ET.Client.UnitRenderComponet))]
    public class AnimatorEventHandler : BEvent<EventType.PlayAnimatorEvent>
    {
        public override void OnEvent(EventType.PlayAnimatorEvent args)
        {
            var component = ModelViewComponent.Instance.GetChild<UnitRenderComponet>(args.UnitId);
            if (component == null)
            {
                Log.Debug($"Not found UnitRener of object{args.UnitId}");
                return;
            }
            if (component.AniData == null)
            {
                var unit = UnitMgr.Instance.GetUnit(args.UnitId);
                Log.Error($"UnitRender({unit?.ZoneObject}) not contains AnimationData component");
                return;
            }

            if (args.CommandType == CMDType.Skill)
            {
                var m = Regex.Match(args.SkillName, "[Ss]kill(\\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 => UnitRenderComponet.CMDIdle,
                    AnimatorEventType.Run => UnitRenderComponet.CMDRun,
                    AnimatorEventType.Dead => UnitRenderComponet.CMDDead,
                    _ => UnitRenderComponet.CMDIdle
                };
                component.AppendCommand(cmd);
            }

            if(!args.Audio.IsNullOrWhitespace())
            {
                //TODO: Playaudio
            }
        }
    }

    [Event(SceneType.None)]
    public class SyncUnitPosEventHandler : BEvent<EventType.SyncUnitPosEvent>
    {
        public override void OnEvent(SyncUnitPosEvent args)
        {
            var unitRender = ModelViewComponent.Instance.GetChild<UnitRenderComponet>(args.Id);
            if(unitRender != null)
            {
                var transform = unitRender.GameObject.transform;
                transform.position = RenderUtils.UnityPosFromBattle(args.Pos);
                transform.rotation = RenderUtils.UnityRotationFromBattle(args.Rotation, args.RotationX);

                if(args.Id == UnitMgr.Instance.ActorId)
                {
                    CameraMgr.FollowMe(transform.position);
                }
                unitRender.SyncHeadBarPos();
            }
            else
            {
                Log.Debug($"Not exist unitRender: {args.Id}");
            }
            //_actor.SendUnitMove(dx, dy, true);
            //(_actor.ZUnit as ZoneActor).SendUnitStopMove();
            //StartSeek(p.X, p.Y, 0, null, false);
        }
    }

    [FriendOf(typeof(UnitRenderComponet))]
    public static class UnitRenerSystem
    {
        [ObjectSystem]
        public class UnitRenerAwakeSystem : AwakeSystem<UnitRenderComponet, GameObject>
        {
            protected override void Awake(UnitRenderComponet self, GameObject go)
            {
                self.GameObject = go;

                self.AniData = self.GameObject.GetComponent<Mono.AnimationData>();
                if (self.AniData != null)
                {
                    self.ExeCommand(UnitRenderComponet.CMDIdle);
                }

                self.HeadPartTrans = go.transform.Find("BindPart/headInfo");
            }
        }

        [ObjectSystem]
        public class UnitRenerUpdateSystem : UpdateSystem<UnitRenderComponet>
        {
            protected override void Update(UnitRenderComponet self)
            {
                if (self.AniData == null) { return; }

                var cmd = self.FilterCmdList();
                if (cmd != null)
                {
                    if (self.DoingCmd?.Type != cmd.Type || cmd.IsSkillCmd())
                    {
                        self.ExeCommand(cmd);
                    }
                }
            }
        }

        [ObjectSystem]
        public class UnitRenerDestroySystem : DestroySystem<UnitRenderComponet>
        {
            protected override void Destroy(UnitRenderComponet self)
            {
                if(self.AniData!= null)
                { 
                    self.AniData.Animancer.Stop();
                }
                GameObjectPool.Instance?.RecycleObject(self.GameObject);
                if(self.HeadBar != null)
                {
                    self.HeadBar.visible = false;
                    GameObjectPool.Instance?.RecycleHeadBar(self.HeadBar);
                }

                self.Reset();
            }
        }

        //===UnitRener 扩展方法-------
        public static void AppendCommand(this UnitRenderComponet self, AnimatorCommand cmd)
        {
            self.Commands.Add(cmd);
        }
        public static void SyncHeadBarPos(this UnitRenderComponet self)
        {
            if (self.HeadBar != null)
            {
                var part = self.HeadPartTrans ?? self.GameObject.transform;
                var pos = Camera.main.WorldToScreenPoint(part.position);
                if(pos.z < 0 || pos.x < 0 || pos.x > Screen.width || pos.y < 0 || pos.y > Screen.height)
                {
                    //不在视野中
                    self.HeadBar.visible = false;
                }
                else
                {
                    var screenpos = pos;
                    pos.y = Screen.height - pos.y;
                    pos = GRoot.inst.GlobalToLocal(pos);
                    self.HeadBar.SetXY(pos.x, pos.y);
                    self.HeadBar.visible = true;
                }
            }
        }
        //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


        //执行指令
        private static void ExeCommand(this UnitRenderComponet self, AnimatorCommand cmd)
        {
            self.DoingCmd = (AnimatorCommand)cmd;

            if(!cmd.IsSkillCmd())
            {
                self.AniData.PlayAnimation(cmd.Type);
            }
            else
            {
                //Skill动作和实际技能时间不太匹配,切到idle动作
                self.AniData.PlayAnimation(cmd.Type, () => {
                    if (self.DoingCmd == cmd)
                    {
                        self.ExeCommand(UnitRenderComponet.CMDIdle);
                    }
                });
            }
        }

        //从指令队列中分析出当前需要执行的指令
        private static AnimatorCommand FilterCmdList(this UnitRenderComponet 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 = UnitRener.CMDIdle;
                }
                else if(next.Type == CMDType.StopSkill && cmd.Type >= CMDType.Skill0 && cmd.Type <= CMDType.Skill3)
                {
                    cmd = UnitRener.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();
                }
            }
            else
            {
                cmds.Clear();
            }
            return cmd;
        }

    }
}