// <auto-generated />
#nullable enable

namespace GFramework.Game.Config.Generated;

/// <summary>
///     Provides a project-level catalog for every config table generated from the current consumer project's schemas.
///     Use this entry point when you want the C# runtime bootstrap path to register all generated tables without repeating one call per schema.
/// </summary>
public static class GeneratedConfigCatalog
{
    /// <summary>
    ///     Describes one generated config table so bootstrap code can enumerate generated domains without re-parsing schema files at runtime.
    /// </summary>
    public readonly struct TableMetadata
    {
        /// <summary>
        ///     Initializes one generated table metadata entry.
        /// </summary>
        /// <param name="configDomain">Logical config domain derived from the schema base name.</param>
        /// <param name="tableName">Runtime registration name.</param>
        /// <param name="configRelativePath">Relative YAML directory path.</param>
        /// <param name="schemaRelativePath">Relative schema file path.</param>
        public TableMetadata(
            string configDomain,
            string tableName,
            string configRelativePath,
            string schemaRelativePath)
        {
            ConfigDomain = configDomain ?? throw new global::System.ArgumentNullException(nameof(configDomain));
            TableName = tableName ?? throw new global::System.ArgumentNullException(nameof(tableName));
            ConfigRelativePath = configRelativePath ?? throw new global::System.ArgumentNullException(nameof(configRelativePath));
            SchemaRelativePath = schemaRelativePath ?? throw new global::System.ArgumentNullException(nameof(schemaRelativePath));
        }

        /// <summary>
        ///     Gets the logical config domain derived from the schema base name.
        /// </summary>
        public string ConfigDomain { get; }

        /// <summary>
        ///     Gets the runtime registration name used by <see cref="global::GFramework.Game.Config.YamlConfigLoader" />.
        /// </summary>
        public string TableName { get; }

        /// <summary>
        ///     Gets the relative directory that stores YAML files for the generated config table.
        /// </summary>
        public string ConfigRelativePath { get; }

        /// <summary>
        ///     Gets the relative schema file path collected by the source generator.
        /// </summary>
        public string SchemaRelativePath { get; }
    }

    /// <summary>
    ///     Gets metadata for every generated config table in the current consumer project.
    /// </summary>
    public static global::System.Collections.Generic.IReadOnlyList<TableMetadata> Tables { get; } = global::System.Array.AsReadOnly(new TableMetadata[]
    {
        new(
            MonsterConfigBindings.Metadata.ConfigDomain,
            MonsterConfigBindings.Metadata.TableName,
            MonsterConfigBindings.Metadata.ConfigRelativePath,
            MonsterConfigBindings.Metadata.SchemaRelativePath),
    });

    /// <summary>
    ///     Tries to resolve generated table metadata by runtime registration name.
    /// </summary>
    /// <param name="tableName">Runtime registration name.</param>
    /// <param name="metadata">Resolved generated table metadata when the registration name exists; otherwise the default value.</param>
    /// <returns><see langword="true" /> when the registration name belongs to a generated config table; otherwise <see langword="false" />.</returns>
    public static bool TryGetByTableName(string tableName, out TableMetadata metadata)
    {
        if (tableName is null)
        {
            throw new global::System.ArgumentNullException(nameof(tableName));
        }

        if (string.Equals(tableName, MonsterConfigBindings.Metadata.TableName, global::System.StringComparison.Ordinal))
        {
            metadata = Tables[0];
            return true;
        }

        metadata = default;
        return false;
    }
}

/// <summary>
///     Captures optional per-table registration overrides for the generated aggregate registration entry point.
/// </summary>
public sealed class GeneratedConfigRegistrationOptions
{
    /// <summary>
    ///     Gets or sets the optional key comparer forwarded to MonsterConfigBindings.RegisterMonsterTable(global::GFramework.Game.Config.YamlConfigLoader, global::System.Collections.Generic.IEqualityComparer<int>?) when aggregate registration runs.
    /// </summary>
    public global::System.Collections.Generic.IEqualityComparer<int>? MonsterComparer { get; init; }
}

/// <summary>
///     Provides a single extension method that registers every generated config table discovered in the current consumer project.
/// </summary>
public static class GeneratedConfigRegistrationExtensions
{
    /// <summary>
    ///     Registers all generated config tables using schema-derived conventions so bootstrap code can stay one-line even as schemas grow.
    /// </summary>
    /// <param name="loader">Target YAML config loader.</param>
    /// <returns>The same loader instance after all generated table registrations have been applied.</returns>
    /// <exception cref="global::System.ArgumentNullException">When <paramref name="loader"/> is null.</exception>
    public static global::GFramework.Game.Config.YamlConfigLoader RegisterAllGeneratedConfigTables(
        this global::GFramework.Game.Config.YamlConfigLoader loader)
    {
        if (loader is null)
        {
            throw new global::System.ArgumentNullException(nameof(loader));
        }

        return RegisterAllGeneratedConfigTables(loader, options: null);
    }

    /// <summary>
    ///     Registers all generated config tables while preserving optional per-table overrides such as custom key comparers.
    /// </summary>
    /// <param name="loader">Target YAML config loader.</param>
    /// <param name="options">Optional per-table overrides for aggregate registration; when null, all tables use their default comparer behavior.</param>
    /// <returns>The same loader instance after all generated table registrations have been applied.</returns>
    /// <exception cref="global::System.ArgumentNullException">When <paramref name="loader"/> is null.</exception>
    public static global::GFramework.Game.Config.YamlConfigLoader RegisterAllGeneratedConfigTables(
        this global::GFramework.Game.Config.YamlConfigLoader loader,
        GeneratedConfigRegistrationOptions? options)
    {
        if (loader is null)
        {
            throw new global::System.ArgumentNullException(nameof(loader));
        }

        options ??= new GeneratedConfigRegistrationOptions();

        loader.RegisterMonsterTable(options.MonsterComparer);
        return loader;
    }
}
