using System.Collections;

namespace PkmnLib.Dynamic.Models;

/// <summary>
/// A collection of Pokemon.
/// </summary>
public interface IPokemonParty : IReadOnlyList<IPokemon?>
{
    /// <summary>
    /// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon.
    /// </summary>
    IPokemon? SwapInto(IPokemon pokemon, int index);

    /// <summary>
    /// Swaps two Pokemon in the party around.
    /// </summary>
    void Swap(int index1, int index2);

    /// <summary>
    /// Whether the party has any Pokemon that could be used in battle.
    /// </summary>
    /// <remarks>
    /// This will return false if all Pokemon are fainted, or eggs, etc.
    /// </remarks>
    bool HasUsablePokemon();
}

/// <inheritdoc />
public class PokemonParty : IPokemonParty
{
    private readonly IPokemon?[] _pokemon;

    /// <inheritdoc cref="PokemonParty" />
    public PokemonParty(int size)
    {
        _pokemon = new IPokemon[size];
    }

    /// <summary>
    /// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon.
    /// </summary>
    public IPokemon? SwapInto(IPokemon pokemon, int index)
    {
        var old = _pokemon[index];
        _pokemon[index] = pokemon;
        return old;
    }

    /// <summary>
    /// Swaps two Pokemon in the party around.
    /// </summary>
    public void Swap(int index1, int index2) =>
        (_pokemon[index1], _pokemon[index2]) = (_pokemon[index2], _pokemon[index1]);


    /// <inheritdoc />
    public bool HasUsablePokemon() => _pokemon.Any(p => p is { IsUsable: true });
    
    /// <inheritdoc />
    public IEnumerator<IPokemon?> GetEnumerator() => ((IEnumerable<IPokemon?>)_pokemon).GetEnumerator();

    /// <inheritdoc />
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

    /// <inheritdoc />
    public int Count => _pokemon.Length;

    /// <inheritdoc />
    public IPokemon? this[int index] => _pokemon[index];
}