using FL.Battle.Buffs;
using System.Collections.Generic;
using UnityEngine;
using XGame;
using XGame.Database;
using XGame.Framework;
using XGame.Framework.Components;
using XGame.Framework.Map;
using XGame.Framework.Time;

namespace FL.Battle.Components
{
    public interface IBuffsContext
    {
        public IEntity Entity { get; }
        public ITimeModule Time { get; }
        public IMapAssetModule Asset { get; }
        Vector3 Position { get; }
        Transform OwnerTr { get; }
        ICombatCalculation Calculation { get; }
        StatesComponent States { get; }
        MoveComponent Move { get; }

    }
    /// <summary>
    /// buff的逻辑控制脚本
    /// </summary>
    public partial class BuffsComponent : Component<IBuffsContext>, IBuffListener
    {
        private Dictionary<long, Buff> _buffsMap = new Dictionary<long, Buff>();
        protected override void OnEnable(object intent)
        {
            TotalShieldVal = 0;
        }
        protected override void OnDisable()
        {
            Clear();
        }
        protected override void OnDispose()
        {
            Clear();
        }
        public bool IsDirty { get; set; }
        public int BuffCount => _buffsMap.Count;
        /// <summary>
        /// 护盾buff是否有变化
        /// </summary>
        public bool IsShieldDirty { get; set; }
        /// <summary>
        /// 所有护盾吸收值
        /// </summary>
        public long TotalShieldVal { get; private set; }
        public void GetBuffs(ref List<IBuff> buffs)
        {
            if (buffs == null)
            {
                buffs = new List<IBuff>();
            }
            else
            {
                buffs.Clear();
            }
            foreach (var buff in _buffsMap.Values)
            {
                if (!buff.IsShowIcon)
                    continue;
                buffs.Add(buff);
            }
        }
        public bool GetElementBuffs(ref List<IBuff> buffs)
        {
            if (buffs == null)
            {
                buffs = new List<IBuff>();
            }
            var lastCount = buffs.Count;
            foreach (var buff in _buffsMap.Values)
            {
                if (buff is ElementAddDebuff element && element.IsReachLayer3())
                {
                    buffs.Add(buff);
                }
            }
            return buffs.Count > lastCount;
        }
        ///// <summary>
        ///// 获取最近的可触发效果的元素buff
        ///// </summary>
        ///// <returns></returns>
        //public IBuff GetPreTickElementBuff()
        //{
        //    Buff result = null;
        //    foreach (var buff in _buffsMap.Values)
        //    {
        //        if (buff.ElementType == EElementType.None)
        //            continue;
        //        if (buff.Layers == buff.LayerLimit)
        //        {
        //            result = buff; 
        //            break;
        //        }
        //        if (result == null || (float)buff.Layers / buff.LayerLimit > (float)result.Layers / result.LayerLimit)
        //        {
        //            result = buff;
        //        }
        //    }
        //    return result;
        //}
        public bool IsContains(EBuffType buffType)
        {
            foreach (var buff in _buffsMap.Values)
            {
                if (buff.BuffType == buffType)
                    return true;
            }
            return false;
        }
        public int GetLayers(long buffId)
        {
            if (_buffsMap.TryGetValue(buffId, out var buff))
            {
                return buff.Layers;
            }
            return 0;
        }
        //void IUpdate.Update(int millisecond)
        //{
        //    _updateBuffs.AddRange(_buffsMap.Values);
        //    foreach (var buff in _updateBuffs)
        //    {
        //        if (buff.Update(millisecond))
        //        {
        //            _buffsMap.Remove(buff.TableId);
        //        }
        //    }
        //    _updateBuffs.Clear();
        //}
        /// <summary>
        /// 护盾吸收
        /// </summary>
        /// <param name="damage"></param>
        /// <returns>护盾吸收后剩余的伤害值 负数</returns>
        public int CalculateShieldAbsorb(int damage)
        {
            if (damage >= 0)
                return damage;
            var tempBuffs = ListPool.Acquire<Buff>();
            tempBuffs.AddRange(_buffsMap.Values);
            foreach (var buff in tempBuffs)
            { // 遍历中buff的数量可能会增减
                if (buff is ShieldBuff shieldBuff)
                {
                    damage = shieldBuff.Reduce(damage);
                    if (damage == 0)
                        break; // 剩余伤害为零，全部吸收了
                }
            }
            ListPool.Recycle(tempBuffs);
            return damage;
        }
        /// <summary>
        /// 获取技能伤害Buff加成
        /// </summary>
        /// <param name="skill"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public int GetDamageAdd(EElementType elementType, IEntity target, BuffsComponent targetBuffs)
        {
            var result = 0;
            foreach (var buff in _buffsMap.Values)
            {
                var buffType = buff.BuffType;
                if (buffType is EBuffType.DizzAdd)
                {
                    if (target.IsState(EEntityState.Dizzy))
                    {
                        result += buff.Table.BuffTypeNum[0];
                    }
                }
                else if (buffType is EBuffType.FreezeAdd)
                {
                    if (target.IsState(EEntityState.Freeze))
                    {
                        result += buff.Table.BuffTypeNum[0];
                    }
                }
                else if (buffType is EBuffType.DotAdd)
                {
                    if (targetBuffs.IsContains(EBuffType.Dot))
                    {
                        result += buff.Table.BuffTypeNum[0];
                    }
                }
                else if (elementType == EElementType.None)
                { // 非元素技能
                    continue;
                }
                else if (buffType != EBuffType.ElementAddIce || target.EntityId != Context.Entity.EntityId ||
                    ((buff as ElementAddDebuff)?.IsReachLayer5(elementType) ?? false))
                { // 目标有冻伤
                    continue;
                }
                else
                {// 目标有冻伤 且 本次攻击没有达到5层元素易伤条件
                    result += buff.Table.BuffTypeNum[1];
                }
            }
            return result;
        }
        /// <summary>
        /// 检测受击目标的buff触发
        /// </summary>
        /// <param name="damage"></param>
        /// <param name="elementType"></param>
        /// <param name="attacker"></param>
        public void TickBuffOrSkill(int damage, EElementType elementType, ICombatCalculation attacker)
        {
            if (elementType == EElementType.None)
                return; // TODO 目前只有元素技能会触发buff
            var tempBuffs = ListPool.Acquire<Buff>();
            tempBuffs.AddRange(_buffsMap.Values);
            foreach (var buff in tempBuffs)
            { // 遍历中buff的数量可能会增减
                if (buff is ElementAddDebuff elementAddDebuff)
                {
                    elementAddDebuff.TryTickBuff(damage, elementType, attacker);
                }
            }
            ListPool.Recycle(tempBuffs);
        }
        public void TryAddBuff(long buffId, int probability, int addLayer = 1, ICombatCalculation attacker = null, int damage = 0)
        {
            if (Context.Entity.IsDead)
                return;
            if (MathUtils.Random(probability) == false)
            {
                return;
            }
            var buff = AddBuff(buffId, addLayer);
            if (attacker != null && buff is ElementAddDebuff elementAddDebuff)
            { // 受击者buff触发攻击者的Buff或者技能
                if (elementAddDebuff.TryTickLayer3(attacker))
                {
                    EventSingle.Instance.Notify(EventDefine.GameMainMapAddBuff, new BuffEventDto()
                    {
                        ownerId = Context.Entity.EntityId,
                        buffTableId = buff.TableId,
                    });
                }
            }
            else if (buff is DotDebuff dotDebuff)
            {
                dotDebuff.TryTickLayer5();
            }
            else if (damage != 0 && buff is ShieldBuff shieldBuff)
            {
                shieldBuff.Add(damage);
            }
            else if (buff.BuffType == EBuffType.Attribute)
            {
                AddAttributeBuff(buff);
            }
        }
        private Buff AddBuff(long buffId, int addLayer)
        {
            IsDirty = true;
            if (_buffsMap.TryGetValue(buffId, out var buff))
            {
                buff.Layers += addLayer;
            }
            else
            {
                var buffTable = BuffTableRepo.Get(buffId);
                buff = GenBuff((EBuffType)buffTable.BuffType);
                buff.Init(buffTable, UIDDefine.New(), Context, this);
                if (addLayer > 1)
                {
                    buff.Layers = addLayer;
                }
                _buffsMap.Add(buff.TableId, buff);
                if (TryToEntityState(buff.BuffType, out var entityState))
                {
                    Context.States.AddState(entityState);
                }
            }
            //Log.Debug($"AddBuff EntityId:{Context.Entity.EntityId} BuffId:{buffId} Overlay:{buff.Layers}");
            return buff;
        }
        private void RemoveBuff(int buffId)
        {
            if (_buffsMap.TryGetValue(buffId, out var buff))
            {
                _buffsMap.Remove(buffId);
                if (TryToEntityState(buff.BuffType, out var entityState))
                { // TODO 需要判断剩余的buff是否有相同类型的状态
                    Context.States.RemoveState(entityState);
                }
                else if (buff is ElementAddDebuff)
                {
                    EventSingle.Instance.Notify(EventDefine.GameMainMapRemoveBuff, new BuffEventDto()
                    {
                        ownerId = Context.Entity.EntityId,
                        buffTableId = buffId,
                    });
                }
                else if (buff is ShieldBuff shieldBuff)
                {
                    // 减去剩余的护盾值
                    (this as IBuffListener).OnShieldChanged(-shieldBuff.Absorption);
                }
                else if (buff.BuffType == EBuffType.Attribute)
                {
                    RemoveAttributeBuff(buff);
                }
                ObjectPool.Recycle(buff);
                IsDirty = true;
            }
        }
        private Buff GenBuff(EBuffType buffType)
        {
            return buffType switch
            {
                EBuffType.Dot => ObjectPool.Acquire<DotDebuff>(),
                EBuffType.Shield => ObjectPool.Acquire<ShieldBuff>(),
                EBuffType.ElementAddFire or EBuffType.ElementAddThunder or EBuffType.ElementAddIce
                or EBuffType.ElementAddPoison or EBuffType.ElementAddWind => ObjectPool.Acquire<ElementAddDebuff>(),
                _ => ObjectPool.Acquire<Buff>(),
            };
        }
        /// <summary>
        /// EBuffType => EEntityState
        /// </summary>
        /// <param name="buffType"></param>
        /// <param name="entityState"></param>
        /// <returns></returns>
        private bool TryToEntityState(EBuffType buffType, out EEntityState entityState)
        {
            switch (buffType)
            {
                case EBuffType.Dizzy:
                    entityState = EEntityState.Dizzy;
                    return true;
                case EBuffType.Freeze:
                    entityState = EEntityState.Freeze;
                    return true;
                case EBuffType.Paralysis:
                    entityState = EEntityState.Palsy;
                    return true;
                default:
                    entityState = EEntityState.Idle;
                    return false;
            }
        }
        private void Clear()
        {
            foreach (var buff in _buffsMap.Values)
            {
                RemoveAttributeValue(buff);
                ObjectPool.Recycle(buff);
            }
            _buffsMap.Clear();
            TotalShieldVal = 0;
            ClearAttributes();
        }
        #region IBuffListener 实现
        void IBuffListener.OnShieldChanged(long val)
        {
            TotalShieldVal += val;
            if (TotalShieldVal < 0)
            {
                Log.Error($"护盾剩余值计算错误.OnShieldChanged total: {TotalShieldVal} value:{val}");
                TotalShieldVal = 0;
            }
            IsShieldDirty = true;

        }
        void IBuffListener.OnCompleted(int buffId)
        {
            RemoveBuff(buffId);
            //Log.Debug($"RemoveBuff EntityId:{Context.Entity.EntityId} BuffId:{buffId}");
        }
        #endregion
    }
}
