namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;

/// <summary>
/// ChangeMoveTypeAbility is a generic ability that changes the type of a move from one type to another.
/// This ability is used by abilities like Normalize, Pixilate, and Refrigerate.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Normalize_(Ability)">Bulbapedia - Normalize</see>
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Pixilate_(Ability)">Bulbapedia - Pixilate</see>
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Refrigerate_(Ability)">Bulbapedia - Refrigerate</see>
/// </summary>
[Script(ScriptCategory.Ability, "change_move_type")]
public class ChangeMoveTypeAbility : Script, IScriptOnInitialize, IScriptChangeMoveType, IScriptChangeBasePower
{
    private StringKey _fromType;
    private StringKey _toType;

    /// <inheritdoc />
    public void OnInitialize(IReadOnlyDictionary<StringKey, object?>? parameters)
    {
        if (parameters == null)
            throw new ArgumentNullException(nameof(parameters));

        if (!parameters.TryGetValue("from_type", out var fromTypeObj) || fromTypeObj is not string fromType)
            throw new ArgumentException("Missing 'from_type' parameter.", nameof(parameters));
        if (!parameters.TryGetValue("to_type", out var toTypeObj) || toTypeObj is not string toType)
            throw new ArgumentException("Missing 'to_type' parameter.", nameof(parameters));
        _fromType = fromType;
        _toType = toType;
    }

    /// <inheritdoc />
    public void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? typeIdentifier)
    {
        var typeLibrary = target.Library.StaticLibrary.Types;
        // Both types must be valid and the current type must match the from type
        if (!typeLibrary.TryGetTypeIdentifier(_fromType, out var fromType) ||
            !typeLibrary.TryGetTypeIdentifier(_toType, out var toType) || typeIdentifier != fromType)
        {
            return;
        }
        move.Battle.EventHook.Invoke(new AbilityTriggerEvent(move.User));
        typeIdentifier = toType;
        move.GetHitData(target, hit).SetFlag("change_move_type_ability");
    }

    /// <inheritdoc />
    public void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
    {
        if (move.GetHitData(target, hit).HasFlag("change_move_type_ability"))
            basePower = basePower.MultiplyOrMax(1.3f);
    }
}