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

package space.rcmd.android.sizzle.ui.toolbox

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.sp
import space.rcmd.android.sizzle.model.ParamSpec
import space.rcmd.android.sizzle.model.ToolboxSlot
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.components.RetroDropdown
import space.rcmd.android.sizzle.ui.theme.LocalRetro
import kotlin.math.roundToInt

/**
 * One editable parameter row. Enumerated params ([ParamSpec.isEnum]) render as a
 * dropdown; numeric params render as a labelled slider. Reading and writing goes
 * through the slot's string-typed value map so it stays serialization-friendly.
 */
@Composable
fun ParamControl(vm: AppViewModel, slot: ToolboxSlot, spec: ParamSpec) {
    val c = LocalRetro.current
    @Suppress("UNUSED_VARIABLE") val rev = vm.revision // subscribe so sliders/dropdowns refresh
    if (spec.isEnum) {
        RetroDropdown(
            label = spec.label,
            options = spec.choices,
            selected = slot.string(spec.key, spec.choices.first()),
            onSelect = { slot.set(spec.key, it); vm.bumpForToolbar() },
            modifier = Modifier.fillMaxWidth(),
        )
    } else {
        val value = slot.float(spec.key, spec.default)
        // Integer params (e.g. bit depth, semitones, octaves) snap to whole values:
        // the slider gets one discrete stop per integer, and writes rounded values.
        val intSteps = if (spec.isInt) ((spec.max - spec.min).toInt() - 1).coerceAtLeast(0) else 0
        Column(Modifier.fillMaxWidth()) {
            Row {
                Text("${spec.label}: ", color = c.textDim,
                    fontFamily = FontFamily.Monospace, fontSize = 11.sp)
                Text(if (spec.isInt) value.roundToInt().toString() else formatValue(value), color = c.text,
                    fontFamily = FontFamily.Monospace, fontSize = 11.sp)
            }
            Slider(
                value = value.coerceIn(spec.min, spec.max),
                valueRange = spec.min..spec.max,
                steps = intSteps,
                onValueChange = {
                    val v = if (spec.isInt) it.roundToInt().toFloat() else it
                    slot.set(spec.key, v); vm.bumpForToolbar()
                },
                colors = SliderDefaults.colors(
                    thumbColor = c.accent, activeTrackColor = c.accent, inactiveTrackColor = c.grid,
                ),
            )
        }
    }
}

private fun formatValue(v: Float): String =
    if (v == v.toInt().toFloat()) v.toInt().toString() else String.format("%.2f", v)
