import tkinter as tk
from dataclasses import dataclass

import ttkbootstrap as ttk


@dataclass
class Parameter:
    var: tk.IntVar | tk.DoubleVar
    slider: ttk.Scale


class ParameterTuner(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, *kwargs)

        self._params: dict[int, Parameter] = {}

    def add(self, name: str, value: int | float, min_value: int | float, max_value: int | float) -> int:
        frame = tk.Frame(self, width=200)

        if isinstance(value, int):
            var = tk.IntVar(frame, value=value)
            labelformat = "{name}: {value}"
        else:
            var = tk.DoubleVar(frame, value=value)
            labelformat = "{name}: {value:.2f}"

        label = tk.Label(frame, text=f"{name}: {var.get()}")
        slider = ttk.Scale(
            frame,
            variable=var,
            from_=min_value,
            to=max_value,
            length=200,
            orient=tk.HORIZONTAL,
        )

        var.trace_add(
            "write",
            lambda v, index, mode: label.configure(text=labelformat.format(name=name, value=var.get())),
        )

        label.pack()
        slider.pack()

        frame.pack(side=tk.RIGHT, padx=10)

        param_id = len(self._params)
        self._params[param_id] = Parameter(var, slider)
        return param_id

    def get(self, param_id: int) -> int | float:
        return self._params[param_id].var.get()

    def set(self, param_id: int, value: int | float):
        self._params[param_id].var.set(value)

    def get_slider(self, param_id: int) -> ttk.Scale:
        return self._params[param_id].slider

    def set_state(self, state: str, param_id: int = None):
        if param_id is not None:
            self._params[param_id].slider.configure(state=state)
        else:
            for param in self._params.values():
                param.slider.configure(state=state)


if __name__ == "__main__":
    main = tk.Tk()
    pt = ParameterTuner(main)
    param1 = pt.add("Frameabstand", 30, 1, 60)
    param2 = pt.add("Schwellenwert", 0.2, 0, 5)
    pt.pack()

    main.mainloop()
