namespace PkmnLib.Dynamic.ScriptHandling;

/// <summary>
/// A script source is an object that can hold scripts, and from which scripts can be executed.
/// </summary>
public interface IScriptSource
{
    /// <summary>
    /// Gets an iterator over all scripts that are relevant for this source.
    /// </summary>
    ScriptIterator GetScripts();
    
    /// <summary>
    /// The number of scripts that are expected to be relevant for this source. This generally is
    /// The number of its own scripts + the number of scripts for any parents.
    /// </summary>
    int ScriptCount { get; }

    /// <summary>
    /// This should add all scripts belonging to this source to the scripts Vec, disregarding its
    /// potential parents.
    /// </summary>
    /// <param name="scripts"></param>
    void GetOwnScripts(List<IEnumerable<ScriptContainer>> scripts);

    /// <summary>
    /// This should add all scripts that are relevant to the source the the scripts Vec, including
    /// everything that belongs to its parents.
    /// </summary>
    /// <param name="scripts"></param>
    void CollectScripts(List<IEnumerable<ScriptContainer>> scripts);
}

/// <inheritdoc />
public abstract class ScriptSource : IScriptSource
{
    /// <inheritdoc />
    public ScriptIterator GetScripts()
    {
        if (_scripts == null)
        {
            _scripts = new List<IEnumerable<ScriptContainer>>(ScriptCount);
            CollectScripts(_scripts);
        }
        return new ScriptIterator(_scripts);
    }

    /// <inheritdoc />
    public abstract int ScriptCount { get; }

    /// <inheritdoc />
    public abstract void GetOwnScripts(List<IEnumerable<ScriptContainer>> scripts);

    /// <inheritdoc />
    public abstract void CollectScripts(List<IEnumerable<ScriptContainer>> scripts);

    private List<IEnumerable<ScriptContainer>>? _scripts;
}