// Full Equalizer APO / Peace filter-type set.
namespace DansoriEQ.Core.Eq;

/// <summary>The "third" adjustable parameter a filter type exposes (besides Fc and Gain).</summary>
public enum FilterParam { None, Q, Slope, Order }

/// <summary>Parametric filter shapes, matching the Equalizer APO / Peace set.</summary>
public enum FilterType
{
    Peaking,                 // PK   — Fc, Gain, Q
    LowPass,                 // LPQ  — Fc, Q
    HighPass,                // HPQ  — Fc, Q
    BandPass,                // BP   — Fc, Q
    LowShelf,                // LS   — Fc, Gain, Q
    HighShelf,               // HS   — Fc, Gain, Q
    Notch,                   // NO   — Fc, Q
    AllPass,                 // AP   — Fc, Q
    LowShelfSlope,           // LSC  — Fc, Gain, Slope(dB/oct)
    HighShelfSlope,          // HSC  — Fc, Gain, Slope(dB/oct)
    LowPassButterworth,      // Fc, Order (even)
    HighPassButterworth,     // Fc, Order (even)
    LowPassLinkwitzRiley,    // Fc, Order (even)
    HighPassLinkwitzRiley,   // Fc, Order (even)
    LowShelfQSlope,          // Fc, Gain, Slope(S)
    HighShelfQSlope,         // Fc, Gain, Slope(S)
    LowShelfCornerQSlope,    // Fc(corner), Gain, Slope(S)
    HighShelfCornerQSlope    // Fc(corner), Gain, Slope(S)
}

public static class FilterTypeExtensions
{
    /// <summary>True if the filter's Gain (dB) is meaningful.</summary>
    public static bool UsesGain(this FilterType t) => t switch
    {
        FilterType.Peaking or FilterType.LowShelf or FilterType.HighShelf
            or FilterType.LowShelfSlope or FilterType.HighShelfSlope
            or FilterType.LowShelfQSlope or FilterType.HighShelfQSlope
            or FilterType.LowShelfCornerQSlope or FilterType.HighShelfCornerQSlope => true,
        _ => false
    };

    /// <summary>Which third parameter (Q / Slope / Order) this type exposes.</summary>
    public static FilterParam ThirdParam(this FilterType t) => t switch
    {
        FilterType.LowShelfSlope or FilterType.HighShelfSlope
            or FilterType.LowShelfQSlope or FilterType.HighShelfQSlope
            or FilterType.LowShelfCornerQSlope or FilterType.HighShelfCornerQSlope => FilterParam.Slope,
        FilterType.LowPassButterworth or FilterType.HighPassButterworth
            or FilterType.LowPassLinkwitzRiley or FilterType.HighPassLinkwitzRiley => FilterParam.Order,
        _ => FilterParam.Q
    };

    /// <summary>Human-readable name (matches the Peace dropdown).</summary>
    public static string DisplayName(this FilterType t) => t switch
    {
        FilterType.Peaking               => "Peak Filter",
        FilterType.LowPass               => "Low Pass Filter",
        FilterType.HighPass              => "High Pass Filter",
        FilterType.BandPass              => "Band Pass Filter",
        FilterType.LowShelf              => "Low Shelf Filter",
        FilterType.HighShelf             => "High Shelf Filter",
        FilterType.Notch                 => "Notch Filter",
        FilterType.AllPass               => "All Pass Filter",
        FilterType.LowShelfSlope         => "Low Shelf Filter (Slope in dB)",
        FilterType.HighShelfSlope        => "High Shelf Filter (Slope in dB)",
        FilterType.LowPassButterworth    => "Low Pass Butterworth (Even Orders)",
        FilterType.HighPassButterworth   => "High Pass Butterworth (Even Orders)",
        FilterType.LowPassLinkwitzRiley  => "Low Pass Linkwitz-Riley (Even Orders)",
        FilterType.HighPassLinkwitzRiley => "High Pass Linkwitz-Riley (Even Orders)",
        FilterType.LowShelfQSlope        => "Low Shelf Filter (Q as Slope)",
        FilterType.HighShelfQSlope       => "High Shelf Filter (Q as Slope)",
        FilterType.LowShelfCornerQSlope  => "Low Shelf Filter (Corner Freq, Q as Slope)",
        FilterType.HighShelfCornerQSlope => "High Shelf Filter (Corner Freq, Q as Slope)",
        _ => t.ToString()
    };

    /// <summary>Short chip label.</summary>
    public static string ShortLabel(this FilterType t) => t switch
    {
        FilterType.Peaking               => "PK",
        FilterType.LowPass               => "LP",
        FilterType.HighPass              => "HP",
        FilterType.BandPass              => "BP",
        FilterType.LowShelf              => "LS",
        FilterType.HighShelf             => "HS",
        FilterType.Notch                 => "NO",
        FilterType.AllPass               => "AP",
        FilterType.LowShelfSlope         => "LSC",
        FilterType.HighShelfSlope        => "HSC",
        FilterType.LowPassButterworth    => "LPB",
        FilterType.HighPassButterworth   => "HPB",
        FilterType.LowPassLinkwitzRiley  => "LPL",
        FilterType.HighPassLinkwitzRiley => "HPL",
        FilterType.LowShelfQSlope        => "LSQ",
        FilterType.HighShelfQSlope       => "HSQ",
        FilterType.LowShelfCornerQSlope  => "LSCQ",
        FilterType.HighShelfCornerQSlope => "HSCQ",
        _ => "PK"
    };

    /// <summary>Primary APO token for single-section types. (Cascade types are emitted by ApoRenderer.)</summary>
    public static string ToApoToken(this FilterType t) => t switch
    {
        FilterType.Peaking               => "PK",
        FilterType.LowPass               => "LPQ",
        FilterType.HighPass              => "HPQ",
        FilterType.BandPass              => "BP",
        FilterType.LowShelf              => "LS",
        FilterType.HighShelf             => "HS",
        FilterType.Notch                 => "NO",
        FilterType.AllPass               => "AP",
        FilterType.LowShelfSlope         => "LSC",
        FilterType.HighShelfSlope        => "HSC",
        FilterType.LowShelfQSlope        => "LS",
        FilterType.HighShelfQSlope       => "HS",
        FilterType.LowShelfCornerQSlope  => "LS",
        FilterType.HighShelfCornerQSlope => "HS",
        _ => "PK"
    };

    public static FilterType FromApoToken(string token) => token.Trim().ToUpperInvariant() switch
    {
        "PK" or "PEQ" or "MODAL" => FilterType.Peaking,
        "LP"                     => FilterType.LowPass,
        "LPQ"                    => FilterType.LowPass,
        "HP"                     => FilterType.HighPass,
        "HPQ"                    => FilterType.HighPass,
        "BP"                     => FilterType.BandPass,
        "LS"                     => FilterType.LowShelf,
        "LSC"                    => FilterType.LowShelfSlope,
        "HS"                     => FilterType.HighShelf,
        "HSC"                    => FilterType.HighShelfSlope,
        "NO" or "NOTCH"          => FilterType.Notch,
        "AP" or "ALLPASS"        => FilterType.AllPass,
        _ => FilterType.Peaking
    };
}
