using PkmnLib.Dynamic.Events;
using PkmnLib.Dynamic.Libraries;
using PkmnLib.Dynamic.Models.Choices;
using PkmnLib.Dynamic.ScriptHandling;

namespace PkmnLib.Dynamic.Models;

/// <summary>
/// A battle is a representation of a battle in the Pokemon games. It contains all the information needed
/// to simulate a battle, and can be used to simulate a battle between two parties.
/// </summary>
public interface IBattle : IScriptSource
{
    /// <summary>
    /// The library the battle uses for handling.
    /// </summary>
    IDynamicLibrary Library { get; }

    /// <summary>
    /// A list of all different parties in the battle.
    /// </summary>
    IReadOnlyList<IBattleParty> Parties { get; }

    /// <summary>
    /// Whether or not Pokemon can flee from the battle.
    /// </summary>
    bool CanFlee { get; }

    /// <summary>
    /// The number of sides in the battle. Typically 2.
    /// </summary>
    byte NumberOfSides { get; }

    /// <summary>
    /// The number of Pokemon that can be on each side.
    /// </summary>
    byte PositionsPerSide { get; }

    /// <summary>
    /// A list of all sides in the battle.
    /// </summary>
    IReadOnlyList<IBattleSide> Sides { get; }

    /// <summary>
    /// The RNG used for the battle.
    /// </summary>
    IBattleRandom Random { get; }

    /// <summary>
    /// Whether the battle has ended.
    /// </summary>
    bool HasEnded { get; }

    /// <summary>
    /// The result of the battle. If the battle has not ended, this is null.
    /// </summary>
    BattleResult? Result { get; }

    /// <summary>
    /// The handler to send all events to.
    /// </summary>
    EventHook EventHook { get; }

    /// <summary>
    /// The index of the current turn. Initially 0, until the first turn starts when all choices are made.
    /// </summary>
    uint CurrentTurnNumber { get; }

    /// <summary>
    /// A queue of the yet to be executed choices in a turn.
    /// </summary>
    BattleChoiceQueue ChoiceQueue { get; }

    /// <summary>
    /// Get a Pokemon on the battlefield, on a specific side and an index on that side.
    /// </summary>
    IPokemon GetPokemon(byte side, byte position);

    /// <summary>
    /// Returns whether a slot on the battlefield can still be filled. If no party is responsible
    /// for that slot, or a party is responsible, but has no remaining Pokemon to throw out anymore,
    /// this returns false.
    /// </summary>
    bool CanSlotBeFilled(byte side, byte position);

    /// <summary>
    /// Validates whether the battle is still in a non-ended state. If the battle has ended, this
    /// properly sets who has won etc.
    /// </summary>
    void ValidateBattleState();

    /// <summary>
    /// Checks whether a choice is actually possible.
    /// </summary>
    void CanUse(ITurnChoice choice);
    
    /// <summary>
    /// Try and set the choice for the battle. If the choice is not valid, this returns false.
    /// </summary>
    bool TrySetChoice(ITurnChoice choice);
    
    /// <summary>
    /// Sets the current weather for the battle. If null is passed, this clears the weather.
    /// </summary>
    void SetWeather(string? weatherName);
    
    /// <summary>
    /// Gets the current weather of the battle. If no weather is present, this returns null.
    /// </summary>
    string? WeatherName { get; }
    
    
    
}