using System.Collections.Generic;
using UnityEngine;
using Game.Battle;
namespace Game
{
    /// 
    /// 实体身上的UI显示,均在此管理
    /// 
    public class PageHeadBar : UIPageBase
    {
        private int _targetCache = 0;
        private readonly Dictionary> _hpBarDict =
            new Dictionary>();
        private readonly Dictionary>> _hitNumDict =
            new Dictionary>>();
        private readonly Dictionary>> _hitBuffDict =
            new Dictionary>>();
        private readonly Dictionary> _interactDict =
            new Dictionary>();
        protected override void OnCreate()
        {
            CreateUI(false);
        }
        protected override void OnOpen()
        {
            //打开时创建所有非主角实体的血条
            var entities = Util.GetGroup(GameMatcher.Interact); //怪物、npc、宝箱、传送门...
            foreach (var entity in entities)
            {
                if (entity.iD.Data.IsDestroy)
                {
                    continue;
                }
                SetHpBar(entity.ID(), true);
                SetHitNum(entity.ID(), true);
                SetInteract(entity.ID(), true);
            }
            EventManager.Instance.AddEvent(EEvent.EntityAlive, OnEntityAlive);
            EventManager.Instance.AddEvent(EEvent.EntityHit, OnEntityHit);
            EventManager.Instance.AddEvent(EEvent.EntityHitText, OnEntityHitText);
            UpdateHeadBarPos(); //打开时更新位置 避免闪烁
        }
        protected override void OnClose()
        {
            foreach (var kvp in _hpBarDict)
            {
                kvp.Value.Destroy();
            }
            _hpBarDict.Clear();
            EventManager.Instance.RemoveEvent(EEvent.EntityAlive, OnEntityAlive);
            EventManager.Instance.RemoveEvent(EEvent.EntityHit, OnEntityHit);
            EventManager.Instance.RemoveEvent(EEvent.EntityHitText, OnEntityHitText);
        }
        public override void FixedUpdate()
        {
            UpdateLock(); //锁定
            UpdateHeadBarPos(); //headBar位置更新
            UpdateHitNum(); //跳字更新
            UpdateHitBuff(); //buff跳字更新
        }
        private void UpdateLock()
        {
            var master = Util.GetMaster();
            var targetId = master.combo.TargetLock;
            var target = Util.GetEntity(targetId);
            View.m_showLock.SetSelectedIndex(target == null ? 0 : 1);
            if (target == null)
                return;
            if (targetId != _targetCache)
            {
                View.m_lock.m_actLock.Play();
                _targetCache = targetId;
            }
            View.m_lock.position = GetScreenPos(Util.EntityViewPos(target));
        }
        private void UpdateHeadBarPos()
        {
            foreach (var kvp in _hpBarDict)
            {
                var entity = Util.GetEntity(kvp.Key);
                if (entity != null)
                {
                    var headBarItem = kvp.Value;
                    var posScreen = GetScreenPos(Util.EntityViewPos(entity));
                    headBarItem.Component.SetPosition(posScreen.x, posScreen.y - 80, posScreen.z);
                }
            }
            foreach (var kvp in _hitNumDict)
            {
                var entity = Util.GetEntity(kvp.Key);
                if (entity != null)
                {
                    var hitNumList = kvp.Value;
                    var posScreen = GetScreenPos(Util.EntityViewPos(entity));
                    foreach (var item in hitNumList)
                    {
                        item.Component.SetPosition(posScreen.x, posScreen.y, posScreen.z);
                    }
                }
            }
            foreach (var kvp in _hitBuffDict)
            {
                var entity = Util.GetEntity(kvp.Key);
                if (entity != null)
                {
                    var hitNumList = kvp.Value;
                    var posScreen = GetScreenPos(Util.EntityViewPos(entity));
                    foreach (var item in hitNumList)
                    {
                        item.Component.SetPosition(posScreen.x, posScreen.y - 40, posScreen.z);
                    }
                }
            }
            foreach (var kvp in _interactDict)
            {
                var entity = Util.GetEntity(kvp.Key);
                if (entity != null)
                {
                    var interactItem = kvp.Value;
                    var posScreen = GetScreenPos(Util.EntityViewPos(entity));
                    interactItem.Component.SetPosition(posScreen.x, posScreen.y - 80, posScreen.z);
                }
            }
        }
        /// 
        /// 更新伤害跳字:更新动效等待时间,等待时间结束播放2阶段动效 2阶段动效结束删除
        /// 
        private void UpdateHitNum()
        {
            foreach (var kvp in _hitNumDict)
            {
                var hitNumList = kvp.Value;
                if (hitNumList.Count == 0)
                {
                    continue;
                }
                var entity = Util.GetEntity(kvp.Key);
                if (entity == null)
                {
                    continue;
                }
                if (entity.pause.IsPause)
                {
                    continue;
                }
                var hp = entity.hp;
                if (hp.DmgShowTime > 0)
                {
                    hp.DmgShowTime -= Time.deltaTime;
                    if (hp.DmgShowTime <= 0)
                    {
                        hp.DmgShowTime = 0;
                        var lastItem = hitNumList[hitNumList.Count - 1].Component as ViewHitNum;
                        lastItem.m_step2.Play();
                        if (GameRandom.Roll(0.5f))
                        {
                            lastItem.m_step3.Play();
                        }
                        else
                        {
                            lastItem.m_step4.Play();
                        }
                    }
                }
                for (int i = hitNumList.Count - 1; i >= 0; i--)
                {
                    if (i == hitNumList.Count - 1 && hp.DmgShowTime > 0)
                    {
                        continue;
                    }
                    var item = hitNumList[i];
                    var hitInfo = hitNumList[i].Component as ViewHitNum;
                    if (!hitInfo.m_step2.playing)
                    {
                        item.Destroy();
                        hitNumList.RemoveAt(i);
                    }
                }
            }
        }
        private void UpdateHitBuff()
        {
            foreach (var kvp in _hitBuffDict)
            {
                var hitNumList = kvp.Value;
                if (hitNumList.Count == 0)
                {
                    continue;
                }
                var entity = Util.GetEntity(kvp.Key);
                if (entity == null)
                {
                    continue;
                }
                if (entity.pause.IsPause)
                {
                    continue;
                }
                for (int i = hitNumList.Count - 1; i >= 0; i--)
                {
                    var item = hitNumList[i];
                    var hitInfo = hitNumList[i].Component as ViewHitBuff;
                    if (entity.pause.IsPause)
                    {
                        hitInfo.m_step1.SetPaused(true);
                        continue;
                    }
                    hitInfo.m_step1.SetPaused(false);
                    if (!hitInfo.m_step1.playing)
                    {
                        item.Destroy();
                        hitNumList.RemoveAt(i);
                    }
                }
            }
        }
        private void OnEntityAlive(PEntityAlive param)
        {
            var entity = param.Entity;
            if (entity == Util.GetMasterID())
            {
                return;
            }
            SetHpBar(param.Entity, param.IsAlive);
            SetHitNum(param.Entity, param.IsAlive);
            SetInteract(param.Entity, param.IsAlive);
        }
        private void SetInteract(int entityID, bool isAlive = true)
        {
            var entity = Util.GetEntity(entityID);
            if (!entity.hasInteract)
            {
                return;
            }
            if (isAlive)
            {
                if (!_interactDict.ContainsKey(entityID))
                {
                    var interactBar = UIManager.Instance.Creator.CreateUIItem(ViewInteract.URL);
                    _interactDict[entityID] = interactBar;
                    var interactComp = interactBar.Component;
                    var interact = entity.interact;
                    BindData(interact.IsActive,
                        (_, now) => { interactComp.m_showInteract.selectedIndex = now ? 1 : 0; });
                    BindData(interact.IsTarget,
                        (_, now) => { interactComp.m_isTarget.selectedIndex = now ? 1 : 0; });
                }
            }
            else
            {
                if (_interactDict.ContainsKey(entityID))
                {
                    _interactDict[entityID].Destroy();
                    _interactDict.Remove(entityID);
                    var interact = entity.interact;
                    UnbindData(interact.IsActive);
                    UnbindData(interact.IsTarget);
                }
            }
        }
        private void SetHitNum(int entityID, bool isAlive = true)
        {
            if (isAlive)
            {
                if (!_hitNumDict.ContainsKey(entityID))
                {
                    _hitNumDict[entityID] = new List>();
                    _hitBuffDict[entityID] = new List>();
                }
            }
            else
            {
                if (_hitNumDict.ContainsKey(entityID))
                {
                    foreach (var item in _hitNumDict[entityID])
                    {
                        item.Destroy();
                    }
                    _hitNumDict.Remove(entityID);
                    foreach (var item in _hitBuffDict[entityID])
                    {
                        item.Destroy();
                    }
                    _hitBuffDict.Remove(entityID);
                }
            }
        }
        private void SetHpBar(int entityID, bool isAlive = true)
        {
            var entity = Util.GetEntity(entityID);
            if (!entity.hasHp)
            {
                return;
            }
            if (isAlive)
            {
                if (!_hpBarDict.ContainsKey(entityID))
                {
                    //创建血条UI
                    var hpBar = UIManager.Instance.Creator.CreateUIItem(Viewc_blood.URL);
                    _hpBarDict[entityID] = hpBar;
                    var hpComp = hpBar.Component;
                    if (entity.hasHp)
                    {
                        var hp = entity.hp;
                        var buff = entity.buff;
                        var ai = entity.aI;
                        //数据绑定
                        BindData(hp.IsDamaged, (_, now) =>
                        {
                            hpComp.m_showhp.selectedIndex = now ? 1 : 0;
                            hpComp.m_showshield.selectedIndex = now && (hp.ShieldMax.Value > 0) ? 1 : 0;
                            //是否显示额外数据
                            var isShowExtra = now && GameSetting.IsShowExtraHeadBar;
                            hpComp.m_showExtra.selectedIndex = isShowExtra ? 1 : 0;
                        });
                        BindData(hp.HpMax, (_, now) =>
                        {
                            hpComp.m_bloodBarEnemy.m_sub.max = now;
                            hpComp.m_bloodBarEnemy.m_tween.max = now;
                            //根据hpMax动态调整血条长度
                            var width = Mathf.Clamp(now, 40, 150);
                            hpComp.m_bloodBarEnemy.width = width;
                            hpComp.m_shieldBarEnemy.width = width;
                        });
                        BindData(hp.Hp, (_, now) =>
                        {
                            hpComp.m_bloodBarEnemy.m_sub.value = now;
                            hpComp.m_bloodBarEnemy.m_tween.TweenValue(now - 1, 0.5f);
                        });
                        BindData(hp.ShieldMax, (_, now) =>
                        {
                            hpComp.m_shieldBarEnemy.m_sub.max = now;
                            hpComp.m_shieldBarEnemy.m_tween.max = now;
                            hpComp.m_showshield.selectedIndex = hp.IsDamaged.Value && (now > 0) ? 1 : 0;
                        });
                        BindData(hp.Shield, (_, now) =>
                        {
                            hpComp.m_shieldBarEnemy.m_sub.value = now;
                            hpComp.m_shieldBarEnemy.m_tween.TweenValue(now - 1, 0.5f);
                            hpComp.m_showshield.selectedIndex = hp.IsDamaged.Value && (now > 0) ? 1 : 0;
                        });
                        BindData(hp.Stun, (_, now) => { hpComp.m_stunBarEnemy.value = now; });
                        BindData(hp.StunMax, (_, now) => { hpComp.m_stunBarEnemy.max = now; });
                        BindData(ai.Hungry, (_, now) => { hpComp.m_hungryBarEnemy.value = now; });
                        BindData(ai.HungryMax, (_, now) => { hpComp.m_hungryBarEnemy.max = now; });
                        BindData(ai.ModuleType, (_, now) => { hpComp.m_moduleType.selectedIndex = (int)now; });
                        BindData(ai.IsHungryFull, (_, now) =>
                        {
                            if (now)
                            {
                                hpComp.m_attackStatus.selectedIndex = 1;
                            }
                        });
                        BindData(ai.AttackPermit, (_, now) =>
                        {
                            if (now)
                            {
                                hpComp.m_attackStatus.selectedIndex = 2;
                            }
                            else
                            {
                                hpComp.m_attackStatus.selectedIndex = 0;
                            }
                        });
                    }
                }
            }
            else
            {
                if (_hpBarDict.ContainsKey(entityID))
                {
                    //销毁血条ui
                    _hpBarDict[entityID].Destroy();
                    _hpBarDict.Remove(entityID);
                    //取消数据绑定
                    if (entity.hasHp)
                    {
                        var hp = entity.hp;
                        var ai = entity.aI;
                        var buff = entity.buff;
                        UnbindData(hp.HpMax);
                        UnbindData(hp.Hp);
                        UnbindData(hp.ShieldMax);
                        UnbindData(hp.Shield);
                        UnbindData(hp.StunMax);
                        UnbindData(hp.Stun);
                        UnbindData(ai.HungryMax);
                        UnbindData(ai.Hungry);
                        UnbindData(ai.ModuleType);
                        UnbindData(ai.IsHungryFull);
                        UnbindData(ai.AttackPermit);
                    }
                }
            }
        }
        private void OnEntityHit(PEntityHit param)
        {
            AddHitNum(param.Target, param.Dmg);
        }
        private void OnEntityHitText(PEntityHitText param)
        {
            AddHitText(param.Target, param.Text);
        }
        private void AddHitNum(int entityID, int dmg)
        {
            if (!_hitNumDict.ContainsKey(entityID))
            {
                return;
            }
            var hitList = _hitNumDict[entityID];
            var hp = Util.GetEntity(entityID).hp;
            ViewHitNum targetItem = null;
            if (hp.DmgShowTime == 0)
            {
                hp.LastDmg = dmg;
                var hitNum = UIManager.Instance.Creator.CreateUIItem(ViewHitNum.URL);
                var item = hitNum.Component as ViewHitNum;
                hitList.Add(hitNum);
                targetItem = item;
            }
            else
            {
                hp.LastDmg += dmg;
                targetItem = hitList[hitList.Count - 1].Component as ViewHitNum;
            }
            targetItem.m_num.text = $"{hp.LastDmg}";
            targetItem.m_step1.Play();
            hp.DmgShowTime = GameConst.HitNumTerm;
        }
        private void AddHitText(int entityID, string text)
        {
            if (!_hitBuffDict.ContainsKey(entityID))
            {
                return;
            }
            var hitList = _hitBuffDict[entityID];
            var hitNum = UIManager.Instance.Creator.CreateUIItem(ViewHitBuff.URL);
            hitList.Add(hitNum);
            var item = hitNum.Component as ViewHitBuff;
            item.m_name.text = text;
            item.m_step1.Play();
        }
    }
}