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

namespace ET.Client
{
    [Event]
    [FriendOf(typeof(ET.Client.UnitRenderComponet))]
    public class AnimatorEventHandler : BEvent<EventType.PlayAnimatorEvent>
    {
        protected override async ETTask OnEvent(EventType.PlayAnimatorEvent args)
        {
            await ETTask.CompletedTask;

            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({component.GameObject.name}) 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 && AnimationType.SkillMax > AnimationType.Skill0 + n)
                    {
                        AnimatorCommand cmd = new AnimatorCommand(AnimationType.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
                {
                    PlayAnimatorEvent.AniType.Idle => UnitRenderComponet.CMDIdle,
                    PlayAnimatorEvent.AniType.Run => UnitRenderComponet.CMDRun,
                    PlayAnimatorEvent.AniType.Dead => UnitRenderComponet.CMDDead,
                    _ => UnitRenderComponet.CMDIdle
                };
                component.AppendCommand(cmd);
            }

            if(!args.Audio.IsNullOrWhitespace())
            {
                //TODO: Playaudio
            }
        }
    }
    [Event]
    [FriendOfAttribute(typeof(ET.Client.UnitRenderComponet))]
    public class ShowVipNameEventHandler : BEvent<ShowVipName>
    {
        protected override async ETTask OnEvent(ShowVipName args)
        {
            await ETTask.CompletedTask;
            var unitRender = ModelViewComponent.Instance.GetChild<UnitRenderComponet>(args.ObjId);
            if (unitRender != null && unitRender.NameBar != null)
            {
                unitRender.NameBar.visible = true;
                unitRender.Vip = args.Vip;
                unitRender.NameBar.color = GameSetting.VipColor[args.Vip];
            }
        }
    }
    [Event]
    [FriendOfAttribute(typeof(ET.Client.UnitRenderComponet))]
    public class UnitDeadEventHandler : BEvent<UnitDead>
    {
        protected override async ETTask OnEvent(UnitDead args)
        {
            var unitRender = ModelViewComponent.Instance.GetChild<UnitRenderComponet>(args.ObjId);
            if (unitRender != null && unitRender.NameBar != null && unitRender.NameBar.visible)
            {
                unitRender.NameBar.color = new Color(0xcc / 255, 0xcc / 255, 0xcc / 255, 1);
            }
            await ETTask.CompletedTask;
        }
    }
    [Event]
    [FriendOfAttribute(typeof(ET.Client.UnitRenderComponet))]
    public class UnitRebirthEventHandler : BEvent<UnitRebirth>
    {
        protected override async ETTask OnEvent(UnitRebirth args)
        {
            var unitRender = ModelViewComponent.Instance.GetChild<UnitRenderComponet>(args.ObjId);
            if (unitRender != null && unitRender.NameBar != null && unitRender.NameBar.visible)
            {
                unitRender.NameBar.color = GameSetting.VipColor[unitRender.Vip];
            }
            await ETTask.CompletedTask;
        }
    }
    [Event]
    public class SyncUnitPosEventHandler : BEvent<EventType.SyncUnitPosEvent>
    {
        protected override async ETTask OnEvent(SyncUnitPosEvent args)
        {
            await ETTask.CompletedTask;
            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);
        }
    }
    [Event]
    public class SyncUnitHpEventHandler : BEvent<EventType.SyncUnitHpEvent>
    {
        protected override async ETTask OnEvent(SyncUnitHpEvent args)
        {
            if (GlobalViewMgr.Instance.HeadbarView.visible)
            {
                var unitRender = ModelViewComponent.Instance.GetChild<UnitRenderComponet>(args.Id);
                if (unitRender != null)
                {
                    unitRender.SyncHeadBarHP(args.Value).Coroutine();
                }
            }
            await ETTask.CompletedTask;
        }
    }

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

                self.AniData = self.GameObject.GetComponent<Mono.AnimationData>();

                self.TransHeadInfo = go.transform.Find("BindPart/headInfo");
                self.FrozenComponent = self.GameObject.GetComponent <Mono.IceFrozen>();
            }
        }

        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);
                    }
                }
            }
        }

        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.TransHeadInfo ?? 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.SetXY(999999, 999999);
                }
                else
                {
                    pos.y = Screen.height - pos.y;
                    pos = GRoot.inst.GlobalToLocal(pos);
                    self.HeadBar.SetXY(pos.x, pos.y);
                }
            }
        }
        public static async ETTask SyncHeadBarHP(this UnitRenderComponet self, float newValue)
        {
            if (self.HPBar != null)
            {
                var old = self.HPBar.value;
                if ((old - newValue) > 20 || (newValue - old > 20 && old > 0))
                {
                    self.HPBar.visible = true;
                    self.HPBar.TweenValue(newValue, 0.6f);
                    await TimerComponent.Instance.WaitAsync(700);
                    self.HPBar.visible = false;
                }
                else
                {
                    self.HPBar.value = newValue;
                }
            }
        }
        public static void PauseAnimation(this UnitRenderComponet self)
        {
            self.AniData.Pause();
        }
        public static void ResumeAnimation(this UnitRenderComponet self)
        {
            self.AniData.Resume();
        }
        public static void SetFrozen(this UnitRenderComponet self)
        {
            self.FrozenComponent?.StartFroze();
        }
        public static void ClearFrozen(this UnitRenderComponet self)
        {
            self.FrozenComponent?.ClearFroze();
        }
        //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


        //执行指令
        private static void ExeCommand(this UnitRenderComponet self, AnimatorCommand cmd)
        {
            self.DoingCmd = (AnimatorCommand)cmd;
            if(self.AniData.IsPauseStatus() && cmd.Type == AnimationType.Dead)
            {
                self.AniData.Resume();
            }

            if(!cmd.IsSkillCmd())
            {
                self.AniData.PlayAnimation(cmd.Type);
            }
            else
            {
                //Skill动作和实际技能时间不太匹配,切到idle动作
                self.AniData.PlayAnimation(cmd.Type, () => {
                    if (self.DoingCmd == cmd && !self.AniData.IsPauseStatus())
                    {
                        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;
        }

    }
}