//
//  UseItemPolicy.cs
//
//  Copyright (c) František Boháček. All rights reserved.
//  Licensed under the MIT license. See LICENSE file in the project root for full license information.

using NosSmooth.Extensions.Combat.Errors;
using NosSmooth.Extensions.Combat.Selectors;
using NosSmooth.Game.Data.Characters;
using NosSmooth.Game.Data.Items;
using Remora.Results;

namespace NosSmooth.Extensions.Combat.Policies;

/// <summary>
/// The policy to use an item.
/// </summary>
/// <param name="UseItems">Whether to use items.</param>
/// <param name="UseBelowHealthPercentage">Use items below the given character's health percentage.</param>
/// <param name="UseBelowManaPercentage">Use items below the given character's mana percentage.</param>
/// <param name="UseHealthItemsVNums">The vnums of the items to use as health items.</param>
/// <param name="UseManaItemsVNums">The vnums of the items to use as mana items.</param>
public record UseItemPolicy
(
    bool UseItems,
    int UseBelowHealthPercentage,
    int UseBelowManaPercentage,
    int[] UseHealthItemsVNums,
    int[] UseManaItemsVNums
) : IItemSelector
{
    /// <inheritdoc />
    public Result<InventoryItem> GetSelectedItem(ICombatState combatState, ICollection<InventoryItem> possibleItems)
    {
        var character = combatState.Game.Character;
        if (character is null)
        {
            return new ItemNotFoundError();
        }

        if (ShouldUseHpItem(character))
        {
            var item = possibleItems.Cast<InventoryItem?>().FirstOrDefault
                (x => UseHealthItemsVNums.Contains(x?.Item.Item?.ItemVNum ?? -1));
            if (item is not null)
            {
                return item.Value;
            }
        }

        if (ShouldUseMpItem(character))
        {
            var item = possibleItems.Cast<InventoryItem?>().FirstOrDefault
                (x => UseManaItemsVNums.Contains(x?.Item.Item?.ItemVNum ?? -1));
            if (item is not null)
            {
                return item.Value;
            }
        }

        return new ItemNotFoundError();
    }

    /// <inheritdoc />
    public Result<bool> ShouldUseItem(ICombatState combatState)
    {
        if (!UseItems)
        {
            return false;
        }

        var character = combatState.Game.Character;
        if (character is null)
        {
            return false;
        }

        return ShouldUseHpItem(character) || ShouldUseMpItem(character);
    }

    private bool ShouldUseHpItem(Character character)
    {
        return character.Hp is not null && character.Hp.Percentage is not null
            && character.Hp.Percentage < UseBelowHealthPercentage;
    }

    private bool ShouldUseMpItem(Character character)
    {
        return character.Mp is not null && character.Mp.Percentage is not null
            && character.Mp.Percentage < UseBelowManaPercentage;
    }
}