using PkmnLib.Dynamic.Plugins;
using PkmnLib.Plugin.Gen7.AI;
using PkmnLib.Plugin.Gen7.Libraries.Battling;
using PkmnLib.Static.Libraries;
using PkmnLib.Static.Species;

namespace PkmnLib.Plugin.Gen7;

public class Gen7PluginConfiguration : IPluginConfiguration
{
    /// <summary>
    /// Whether the damage calculator has randomness or not. If set to false, the damage calculator will always return
    /// the same value for the same inputs. If set to true, the damage calculator will randomize the damage output
    /// between 0.85 and 1.00 of the calculated damage.
    ///
    /// This should be set to true for most cases, as it simulates the actual damage calculation in the games. Only
    /// set to false for testing purposes.
    /// </summary>
    public bool DamageCalculatorHasRandomness { get; set; } = true;

    /// <summary>
    /// The number of times a species has been caught. This is used for critical capture calculations.
    /// </summary>
    public Func<ISpecies, int> TimesSpeciesCaught { get; set; } = _ => 0;
}

public class Gen7Plugin : Plugin<Gen7PluginConfiguration>, IResourceProvider
{
    public Gen7Plugin() : base(new Gen7PluginConfiguration())
    {
    }

    /// <inheritdoc />
    public Gen7Plugin(Gen7PluginConfiguration configuration) : base(configuration)
    {
    }

    /// <inheritdoc />
    public override string Name => "Gen7";

    /// <inheritdoc />
    public override uint LoadOrder => 0;

    /// <inheritdoc />
    public override void Register(ScriptRegistry registry)
    {
        registry.RegisterAssemblyScripts(typeof(Gen7Plugin).Assembly);
        registry.RegisterBattleStatCalculator(new Gen7BattleStatCalculator());
        registry.RegisterDamageCalculator(new Gen7DamageCalculator(Configuration));
        registry.RegisterMiscLibrary(new Gen7MiscLibrary());
        registry.RegisterCaptureLibrary(new Gen7CaptureLibrary(Configuration));
        registry.RegisterExperienceGainCalculator(new Gen7ExperienceGainCalculator());

        ExplicitAIFunctionRegistration.RegisterAIFunctions(registry.ExplicitAIHandlers);
    }

    /// <inheritdoc />
    public LibrarySettings Settings => new()
    {
        MaxLevel = 100,
        ShinyRate = 4096,
    };

    /// <inheritdoc />
    IResourceResult IResourceProvider.GetResource(ResourceFileType request)
    {
        return request switch
        {
            ResourceFileType.Types => new AssemblyResourceResult("PkmnLib.Plugin.Gen7.Data.Types.csv",
                typeof(Gen7Plugin).Assembly),
            ResourceFileType.Natures => new AssemblyResourceResult("PkmnLib.Plugin.Gen7.Data.Natures.csv",
                typeof(Gen7Plugin).Assembly),
            ResourceFileType.Moves => new AssemblyResourceResult("PkmnLib.Plugin.Gen7.Data.Moves.jsonc",
                typeof(Gen7Plugin).Assembly),
            ResourceFileType.Items => new AssemblyResourceResult("PkmnLib.Plugin.Gen7.Data.Items.json",
                typeof(Gen7Plugin).Assembly),
            ResourceFileType.Abilities => new AssemblyResourceResult("PkmnLib.Plugin.Gen7.Data.Abilities.jsonc",
                typeof(Gen7Plugin).Assembly),
            ResourceFileType.GrowthRates => new AssemblyResourceResult("PkmnLib.Plugin.Gen7.Data.GrowthRates.json",
                typeof(Gen7Plugin).Assembly),
            ResourceFileType.Species => new AssemblyResourceResult("PkmnLib.Plugin.Gen7.Data.Pokemon.json",
                typeof(Gen7Plugin).Assembly),
            _ => throw new ArgumentOutOfRangeException(nameof(request), request, null),
        };
    }
}