/// <summary>
        /// Loads the status effects for the <see cref="CharacterStatusEffects.Character"/> that this collection belongs to from
        /// the database.
        /// </summary>
        public void Load()
        {
            Debug.Assert(_statusEffects.Count == 0, "Why is Load() being called while there are active effects here already?");

            var values = Character.DbController.GetQuery <SelectCharacterStatusEffectsQuery>().Execute(Character.ID);

            var currentTime = GetTime();

            // Load in the ActiveStatusEffects using the values read from the database
            foreach (var value in values)
            {
                var statusEffect = _statusEffectManager.Get(value.StatusEffect);
                if (statusEffect == null)
                {
                    const string errmsg = "Failed to get the StatusEffectBase for StatusEffectType `{0}` on Character `{1}`.";
                    if (log.IsErrorEnabled)
                    {
                        log.ErrorFormat(errmsg, value.StatusEffect, Character);
                    }
                    Debug.Fail(string.Format(errmsg, value.StatusEffect, Character));
                    continue;
                }

                var ase       = new ActiveStatusEffect(statusEffect, value.Power, (TickCount)(value.TimeLeftSecs * 1000 + currentTime));
                var aseWithID = new ASEWithID(value.ID, ase);
                _statusEffects.Add(aseWithID);
                OnAdded(ase);
            }
        }
        /// <summary>
        /// When overridden in the derived class, tries to add an <see cref="IStatusEffect{StatType, StatusEffectType}"/> to
        /// this collection.
        /// </summary>
        /// <param name="statusEffect">The status effect to add.</param>
        /// <param name="power">The power of the status effect.</param>
        /// <returns>True if the <paramref name="statusEffect"/> of the given <paramref name="power"/> was added
        /// to this collection; otherwise false.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="statusEffect" /> is <c>null</c>.</exception>
        public override bool TryAdd(IStatusEffect <StatType, StatusEffectType> statusEffect, ushort power)
        {
            if (statusEffect == null)
            {
                throw new ArgumentNullException("statusEffect");
            }

            ActiveStatusEffect existingStatusEffect;
            var alreadyExists = TryGetStatusEffect(statusEffect.StatusEffectType, out existingStatusEffect);

            var time        = GetTime();
            var disableTime = (TickCount)(time + statusEffect.GetEffectTime(power));

            if (alreadyExists)
            {
                var changed = existingStatusEffect.MergeWith(time, power, disableTime);
                if (changed)
                {
                    RecalculateStatBonuses();
                }
                return(changed);
            }
            else
            {
                var ase = new ActiveStatusEffect(statusEffect, power, disableTime);
                _statusEffects.Add(ase);
                OnAdded(ase);
                return(true);
            }
        }
        /// <summary>
        /// Inserts a new <see cref="ActiveStatusEffect"/> into the database.
        /// </summary>
        /// <param name="item">The <see cref="ActiveStatusEffect"/> to insert.</param>
        /// <returns>The <see cref="ActiveStatusEffectID"/> for the <paramref name="item"/>.</returns>
        ActiveStatusEffectID InsertInDatabase(ActiveStatusEffect item)
        {
            // Convert the time
            var secsLeft = GetSecsLeft(item);

            // Create the row
            var values = new CharacterStatusEffectTable
            {
                CharacterID  = Character.ID,
                ID           = new ActiveStatusEffectID(_dbController.ConnectionPool.AutoIncrementValue),
                Power        = item.Power,
                TimeLeftSecs = (ushort)secsLeft,
                StatusEffect = item.StatusEffect.StatusEffectType
            };

            // Insert the data, and get the ID
            long id;

            _insertQuery.ExecuteWithResult(values, out id);

            Debug.Assert(id <= int.MaxValue);
            Debug.Assert(id >= int.MinValue);

            // Return the ID
            return(new ActiveStatusEffectID((int)id));
        }
        /// <summary>
        /// When overridden in the derived class, handles removing an expired StatusEffect.
        /// </summary>
        /// <param name="activeStatusEffect">StatusEffect to be removed.</param>
        protected override void HandleExpired(ActiveStatusEffect activeStatusEffect)
        {
            // Loop through the _statusEffects list until we find 'activeStatusEffect'
            for (var i = 0; i < _statusEffects.Count; i++)
            {
                var item = _statusEffects[i];
                if (item.Value != activeStatusEffect)
                {
                    continue;
                }

                // Found it - now remove it from the list
                _statusEffects.RemoveAt(i);

                // Raise removal event
                OnRemoved(activeStatusEffect);

                // Remove from database
                DeleteFromDatabase(item.ID);

                return;
            }

            Debug.Fail("Couldn't find the activeStatusEffect in the collection. Where'd it go...?");
        }
        /// <summary>
        /// Gets the number of seconds left for an <see cref="ActiveStatusEffect"/>.
        /// </summary>
        /// <param name="ase">The <see cref="ActiveStatusEffect"/>.</param>
        /// <returns>The number of seconds left for an <see cref="ActiveStatusEffect"/>.</returns>
        int GetSecsLeft(ActiveStatusEffect ase)
        {
            var secsLeft = (int)Math.Round((ase.DisableTime - GetTime()) / 1000f);

            if (secsLeft < 1)
            {
                secsLeft = 1;
            }

            return(secsLeft);
        }
        /// <summary>
        /// When overridden in the derived class, handles removing an expired StatusEffect.
        /// </summary>
        /// <param name="activeStatusEffect">StatusEffect to be removed.</param>
        protected override void HandleExpired(ActiveStatusEffect activeStatusEffect)
        {
            // Remove the item from the list
            var wasRemoved = _statusEffects.Remove(activeStatusEffect);

            // Raise removal event (assuming it was properly removed like it should have been)
            if (wasRemoved)
            {
                OnRemoved(activeStatusEffect);
            }

            Debug.Assert(wasRemoved, "Couldn't find the activeStatusEffect in the collection. Where'd it go...?");
        }
        /// <summary>
        /// When overridden in the derived class, tries to get the <see cref="ActiveStatusEffect"/> for a <see cref="StatusEffectType"/>
        /// in this collection.
        /// </summary>
        /// <param name="statusEffectType">The <see cref="StatusEffectType"/> to try to get the <see cref="ActiveStatusEffect"/> of.</param>
        /// <param name="statusEffect">When this method returns true, contains the <see cref="ActiveStatusEffect"/> instance from
        /// this collection for the given <paramref name="statusEffectType"/>.</param>
        /// <returns>True if the <see cref="ActiveStatusEffect"/> of the <paramref name="statusEffectType"/> was found in
        /// this collection; otherwise false.</returns>
        public override bool TryGetStatusEffect(StatusEffectType statusEffectType, out ActiveStatusEffect statusEffect)
        {
            foreach (var activeStatusEffect in this)
            {
                if (activeStatusEffect.StatusEffect.StatusEffectType == statusEffectType)
                {
                    statusEffect = activeStatusEffect;
                    return(true);
                }
            }

            statusEffect = null;
            return(false);
        }
        /// <summary>
        /// When overridden in the derived class, tries to add an <see cref="IStatusEffect{StatType, StatusEffectType}"/> to
        /// this collection.
        /// </summary>
        /// <param name="statusEffect">The status effect to add.</param>
        /// <param name="power">The power of the status effect.</param>
        /// <returns>True if the <paramref name="statusEffect"/> of the given <paramref name="power"/> was added
        /// to this collection; otherwise false.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="statusEffect" /> is <c>null</c>.</exception>
        public override bool TryAdd(IStatusEffect <StatType, StatusEffectType> statusEffect, ushort power)
        {
            if (statusEffect == null)
            {
                throw new ArgumentNullException("statusEffect");
            }

            ASEWithID existingStatusEffect;
            var       alreadyExists = TryGetStatusEffect(statusEffect.StatusEffectType, out existingStatusEffect);

            var time        = GetTime();
            var disableTime = (TickCount)(time + statusEffect.GetEffectTime(power));

            if (alreadyExists)
            {
                // Status effect already exists - merge with it
                var changed = existingStatusEffect.Value.MergeWith(time, power, disableTime);
                if (changed)
                {
                    RecalculateStatBonuses();
                    UpdateInDatabase(existingStatusEffect);
                }
                return(changed);
            }
            else
            {
                // Status effect doesn't exist - create new instance
                var ase = new ActiveStatusEffect(statusEffect, power, disableTime);

                var id = InsertInDatabase(ase);

                var aseWithID = new ASEWithID(id, ase);
                _statusEffects.Add(aseWithID);

                OnAdded(aseWithID.Value);

                return(true);
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ASEWithID"/> struct.
 /// </summary>
 /// <param name="id">The <see cref="ActiveStatusEffectID"/>.</param>
 /// <param name="value">The <see cref="ActiveStatusEffect"/>.</param>
 public ASEWithID(ActiveStatusEffectID id, ActiveStatusEffect value)
 {
     _id    = id;
     _value = value;
 }