// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later

package space.rcmd.android.sizzle.model

/**
 * Factory data for the [ToolboxType.AMBIENCE] reverb, ported from OTODESK's
 * "Ambience 1.0.1" (a 16-channel FDN reverb). Only the tunables and the 21 factory
 * presets are carried over — the plugin's graphic EQ, output EQ/cut filters and
 * visualizers are intentionally left out. Stereo width and the per-band Pro-mode
 * controls don't apply to this app's mono per-channel FX chain and are omitted too.
 *
 * A preset simply pins the reverb's parameters to a modelled acoustic space; the
 * [AmbienceEditor] writes these values straight into the slot's value map, after
 * which the user can freely tweak any control.
 */
object AmbiencePresets {

    /** The 7 reverb algorithms (topologies), index-aligned with the DSP. */
    val ALGORITHMS = listOf("Room 1", "Room 2", "Hall 1", "Hall 2", "Plate", "Spring", "Goldfoil")

    data class Preset(
        val name: String,
        val algo: Int,
        val preDelay: Float,
        val roomSize: Float,
        val decay: Float,
        val hfDamp: Float,
        val lfAbsorb: Float,
        val diffusion: Float,
        val modAmount: Float,
        val modRate: Float,
        val erLevel: Float,
        val saturation: Float,
        val wetDb: Float,
        val dryDb: Float,
    )

    /** The 21 factory spaces, values transcribed from the original `.ambpreset` files. */
    val FACTORY: List<Preset> = listOf(
        Preset("Abbey Road", 0, 10f, 0.75f, 0.45f, 0f, 0f, 0.55f, 0.15f, 0.30f, 0.70f, 0.08f, -6f, 0f),
        Preset("Abbey Road 2", 1, 10f, 1.60f, 1.80f, 0f, 0f, 0.70f, 0.25f, 0.40f, 0.60f, 0.08f, -4f, 0f),
        Preset("Capitol Studio A", 1, 10f, 1.35f, 1.40f, 0f, 0f, 0.65f, 0.20f, 0.35f, 0.65f, 0.10f, -4f, 0f),
        Preset("Skywalker Sound", 1, 10f, 1.70f, 2.00f, 0f, 0f, 0.75f, 0.30f, 0.45f, 0.55f, 0.06f, -4f, 0f),
        Preset("Carnegie Hall", 2, 10f, 1.50f, 1.70f, 0f, 0f, 0.72f, 0.20f, 0.30f, 0.55f, 0.08f, -4f, 0f),
        Preset("Tokyo Opera City", 2, 10f, 1.65f, 2.00f, 0f, 0f, 0.75f, 0.25f, 0.35f, 0.50f, 0.06f, -4f, 0f),
        Preset("Berlin Konzerthaus", 2, 10f, 1.60f, 2.00f, 0f, 0f, 0.73f, 0.22f, 0.32f, 0.52f, 0.07f, 0f, 0f),
        Preset("Vienna Musikverein", 3, 10f, 1.80f, 2.05f, 0f, 0f, 0.80f, 0.25f, 0.30f, 0.50f, 0.07f, -4f, 0f),
        Preset("Boston Symphony", 3, 10f, 1.70f, 1.85f, 0f, 0f, 0.78f, 0.22f, 0.28f, 0.52f, 0.06f, -4f, 0f),
        Preset("Concertgebouw", 3, 10f, 1.85f, 2.05f, 0f, 0f, 0.82f, 0.28f, 0.32f, 0.48f, 0.06f, -4f, 0f),
        Preset("EMT140 Vocal", 4, 10f, 1.00f, 1.80f, 0f, 0f, 0.85f, 0.30f, 0.50f, 0.40f, 0.12f, -4f, 0f),
        Preset("EMT140 Snare", 4, 10f, 0.80f, 1.00f, 0f, 0f, 0.80f, 0.20f, 0.45f, 0.35f, 0.15f, -4f, 0f),
        Preset("Dark Plate", 4, 10f, 1.20f, 2.50f, 0f, 0f, 0.88f, 0.35f, 0.55f, 0.10f, 0.10f, -4f, 0f),
        Preset("Surf Guitar", 5, 10f, 0.70f, 1.50f, 0f, 0f, 0.45f, 0.50f, 0.70f, 0.45f, 0.20f, -4f, 0f),
        Preset("Vintage Studio", 4, 10f, 0.85f, 2.20f, 0f, 0f, 0.50f, 0.55f, 0.65f, 0.40f, 0.35f, -4f, 0f),
        Preset("Deep Tank", 5, 10f, 1.10f, 3.50f, 0f, 0f, 0.55f, 0.60f, 0.60f, 0.38f, 0.45f, -4f, 0f),
        Preset("Gothic Cathedral", 6, 10f, 2.00f, 8.00f, 0f, 0f, 0.90f, 0.40f, 0.25f, 0.35f, 0.05f, -4f, 0f),
        Preset("Stone Chamber", 6, 10f, 1.80f, 4.00f, 0f, 0f, 0.85f, 0.45f, 0.30f, 0.40f, 0.20f, -4f, 0f),
        Preset("Infinite Space", 6, 10f, 2.00f, 12.00f, 0f, 0f, 0.95f, 0.65f, 0.28f, 0.25f, 0.10f, -4f, 0f),
        Preset("Drums in a Box", 0, 10f, 0.55f, 0.30f, 0f, 0f, 0.40f, 0.10f, 0.20f, 0.80f, 0.05f, -4f, 0f),
        Preset("Tracking Room", 0, 10f, 0.90f, 0.60f, 0f, 0f, 0.65f, 0.20f, 0.35f, 0.65f, 0.10f, -4f, 0f),
    )

    val NAMES: List<String> get() = FACTORY.map { it.name }

    /** Write [preset]'s values into [slot]'s parameter map. */
    fun apply(slot: ToolboxSlot, preset: Preset) {
        slot.set("algo", ALGORITHMS[preset.algo.coerceIn(0, ALGORITHMS.lastIndex)])
        slot.set("predelay", preset.preDelay)
        slot.set("roomsize", preset.roomSize)
        slot.set("decay", preset.decay)
        slot.set("hfdamp", preset.hfDamp)
        slot.set("lfabsorb", preset.lfAbsorb)
        slot.set("diffusion", preset.diffusion)
        slot.set("modamt", preset.modAmount)
        slot.set("modrate", preset.modRate)
        slot.set("erlevel", preset.erLevel)
        slot.set("saturation", preset.saturation)
        slot.set("wet", preset.wetDb)
        slot.set("dry", preset.dryDb)
    }
}
