using System.Collections.Generic;
using UnityEngine;
using XGame.Database;
using XGame.Framework;
using XGame.Framework.Interfaces;
using XGame.Framework.Time;

namespace FL.Battle.Buffs
{
    /// <summary>
    /// 护盾类buff
    /// </summary>
    public class ShieldBuff : Buff
    {
        private class ShieldDto : IReference
        {
            /// <summary>
            /// 吸收值
            /// </summary>
            public int absorption;
            public ITimer timer;

            void IReference.Clear()
            {
                absorption = 0;
                timer?.Cancel();
                timer = null;
            }
        }
        public override int LayerLimit => 1;
        private List<ShieldDto> _shields = new();

        private long _absorption;
        /// <summary>
        /// 剩余吸收值
        /// </summary>
        public long Absorption => _absorption;
        public override bool IsShowIcon => false;
        /// <summary>
        /// 增加吸收值
        /// </summary>
        /// <param name="absorption"></param>
        public void Add(int absorption)
        {
            var rate = Table.BuffTypeNum[0].ToRealFloat();
            absorption = Mathf.RoundToInt(Mathf.Abs(absorption) * rate);
            _absorption += absorption;
            var dto = ObjectPool.Acquire<ShieldDto>();
            _shields.Add(dto);
            dto.absorption = absorption;
            dto.timer = Context.Time.AddDelayTimer(Duration, () =>
            {
                //单个护盾时间到了, 减掉护盾剩余的吸收值
                _absorption -= dto.absorption;
                //移除
                _shields.Remove(dto);
                Listener?.OnShieldChanged(-dto.absorption);
                //回收
                ObjectPool.Recycle(dto);
                XGame.Log.Debug($"护盾{EntityId} 到时结束, 吸收值:{dto.absorption} 总吸收值:{_absorption}");
            });
            Listener?.OnShieldChanged(absorption);
            XGame.Log.Debug($"护盾{EntityId} 增加吸收值:{absorption} 总吸收值:{_absorption}");
        }
        /// <summary>
        /// 护盾吸收
        /// </summary>
        /// <param name="damage"></param>
        /// <returns>护盾吸收后剩余的伤害值 负数</returns>
        public int Reduce(int damage)
        {
            var remain = Mathf.Abs(damage);
            if (remain >= _absorption)
            { // 伤害值大于等于剩余吸收值
                remain = (int)(_absorption - remain);
                XGame.Log.Debug($"护盾{EntityId} 伤害破盾, 吸收:{_absorption} 伤害剩余:{remain}");
                // 没有吸收值了，护盾结束
                Listener?.OnCompleted(TableId);
                return remain;
            }
            var last = _absorption;
            for (var i = 0; i < _shields.Count;)
            {
                var dto = _shields[i];
                if (dto.absorption > remain)
                {
                    dto.absorption -= remain;
                    _absorption -= remain;
                    break;
                }
                remain -= dto.absorption;
                _absorption -= dto.absorption;
                _shields.RemoveAt(i);
                ObjectPool.Recycle(dto);
            }
            Listener?.OnShieldChanged(_absorption - last);
            XGame.Log.Debug($"护盾{EntityId} 吸收了伤害:{damage} 护盾剩余:{_absorption} 吸收前:{last}");
            return 0;
        }
        protected override void OnInited()
        {
            _absorption = 0;
        }
        protected override void OnDispose()
        {
            _absorption = 0;
            foreach (var shield in _shields)
            {
                ObjectPool.Recycle(shield);
            }
            _shields.Clear();
        }
    }
}
