using PkmnLib.Dynamic.ScriptHandling;
using PkmnLib.Static.Utils;

namespace PkmnLib.Dynamic.Models.Choices;

/// <summary>
/// A choice that is made at the beginning of a turn. This can be a switch, flee, item, or pass choice.
/// </summary>
public interface ITurnChoice : IScriptSource, IDeepCloneable
{
    /// <summary>
    /// The user of the turn choice
    /// </summary>
    IPokemon User { get; }

    /// <summary>
    /// The speed of the user at the beginning of the turn.
    /// </summary>
    uint Speed { get; set; }

    /// <summary>
    /// This random value is set at the beginning of the turn. It is used for tie breaking of the
    /// turn order in a predictable way, regardless of implementation and hardware.
    /// </summary>
    uint RandomValue { get; set; }

    /// <summary>
    /// Whether the choice has failed. A failed choice will stop running, and execute special
    /// fail handling during turn execution.
    /// </summary>
    bool HasFailed { get; }

    /// <summary>
    /// Fails the choice. This will prevent it from executing and run a specific fail handling during
    /// execution. Note that this can not be undone.
    /// </summary>
    public void Fail();
}

/// <summary>
/// A basic implementation of a <see cref="ITurnChoice"/>.
/// </summary>
public abstract class TurnChoice : ScriptSource, ITurnChoice
{
    /// <inheritdoc cref="TurnChoice"/>
    protected TurnChoice(IPokemon user)
    {
        User = user;
    }

    /// <summary>
    /// The Pokemon for which the choice is made.
    /// </summary>
    public IPokemon User { get; }

    /// <summary>
    /// The speed of the user at the beginning of the turn.
    /// </summary>
    /// <remarks>
    /// As a developer you do not need to set this value. It is set at the beginning of a turn automatically.
    /// </remarks>
    public uint Speed { get; set; }

    /// <summary>
    /// A random value that is set at the beginning of the turn. This is used for tie breaking of the turn order.
    /// </summary>
    /// <remarks>
    /// As a developer you do not need to set this value. It is set at the beginning of a turn automatically.
    /// </remarks>
    public uint RandomValue { get; set; }

    /// <summary>
    /// Whether the choice has failed. A failed choice will stop running, and execute special fail handling
    /// during turn execution.
    /// </summary>
    public bool HasFailed { get; private set; }

    /// <summary>
    /// Fail the choice. This will prevent it from executing and run a specific fail handling during execution.
    /// </summary>
    public void Fail()
    {
        HasFailed = true;
    }
}