using PkmnLib.Static.Utils;

namespace PkmnLib.Dynamic.Models;

/// <summary>
/// A battle party is a wrapper around a Pokemon party that provides additional functionality for battles.
/// It indicates for which side and position the party is responsible.
/// </summary>
public interface IBattleParty : IDeepCloneable
{
    /// <summary>
    /// The backing Pokemon party.
    /// </summary>
    IPokemonParty Party { get; }

    /// <summary>
    /// Whether the party is responsible for the specified side and position.
    /// </summary>
    bool IsResponsibleForIndex(ResponsibleIndex index);

    /// <summary>
    /// Whether the party has a living Pokemon left that is not in the field.
    /// </summary>
    bool HasUsablePokemonNotInField();

    /// <summary>
    /// Gets all usable Pokemon that are not currently in the field.
    /// </summary>
    IEnumerable<IPokemon> GetUsablePokemonNotInField();
}

/// <summary>
/// A position on the battlefield that a party is responsible for.
/// Contains the index of the side and the position on that side.
/// </summary>
public record struct ResponsibleIndex(byte Side, byte Position);

/// <inheritdoc />
public class BattlePartyImpl : IBattleParty
{
    private readonly ResponsibleIndex[] _responsibleIndices;

    /// <inheritdoc cref="BattlePartyImpl"/>
    public BattlePartyImpl(IPokemonParty party, ResponsibleIndex[] responsibleIndices)
    {
        Party = party;
        _responsibleIndices = responsibleIndices;
    }

    /// <inheritdoc />
    public IPokemonParty Party { get; }

    /// <inheritdoc />
    public bool IsResponsibleForIndex(ResponsibleIndex index) => _responsibleIndices.Contains(index);

    /// <inheritdoc />
    public bool HasUsablePokemonNotInField() =>
        Party.WhereNotNull().Any(x => x.IsUsable && x.BattleData?.IsOnBattlefield != true);

    /// <inheritdoc />
    public IEnumerable<IPokemon> GetUsablePokemonNotInField() =>
        Party.WhereNotNull().Where(x => x.IsUsable && x.BattleData?.IsOnBattlefield != true);
}