from __future__ import annotations

from copy import deepcopy
from typing import Any

from PySide6.QtCore import Qt, Signal
from PySide6.QtWidgets import (
    QCheckBox,
    QDialog,
    QFormLayout,
    QHBoxLayout,
    QLabel,
    QPushButton,
    QSlider,
    QSpinBox,
    QVBoxLayout,
    QWidget,
)


CAMERA_PROPERTY_LABELS = {
    "brightness": "Jasnosc",
    "contrast": "Kontrast",
    "saturation": "Nasycenie",
    "hue": "Barwa",
    "gain": "Gain",
    "exposure": "Ekspozycja",
    "sharpness": "Ostrosc",
    "auto_exposure": "Auto ekspozycja",
    "focus": "Focus",
    "auto_focus": "Auto focus",
}


class PropertySlider(QWidget):
    value_changed = Signal(str, object)

    def __init__(self, name: str, value: float | None) -> None:
        super().__init__()
        self.name = name
        self.enabled_box = QCheckBox()
        self.enabled_box.setChecked(value is not None)
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(-100, 100)
        self.slider.setValue(int(value) if value is not None else 0)
        self.value_box = QSpinBox()
        self.value_box.setRange(-100, 100)
        self.value_box.setValue(self.slider.value())

        layout = QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.enabled_box)
        layout.addWidget(self.slider, 1)
        layout.addWidget(self.value_box)

        self.slider.valueChanged.connect(self.value_box.setValue)
        self.value_box.valueChanged.connect(self.slider.setValue)
        self.slider.valueChanged.connect(self._emit_value)
        self.enabled_box.toggled.connect(self._emit_value)

    def _emit_value(self) -> None:
        self.value_changed.emit(self.name, self.value())

    def value(self) -> float | None:
        if not self.enabled_box.isChecked():
            return None
        return float(self.slider.value())


class SettingsDialog(QDialog):
    settings_saved = Signal(dict)

    def __init__(self, config: dict[str, Any], parent: QWidget | None = None) -> None:
        super().__init__(parent)
        self.setWindowTitle("Ustawienia obrazu")
        self.setMinimumWidth(520)
        self.config = deepcopy(config)
        self.property_widgets: dict[str, PropertySlider] = {}

        camera_cfg = self.config["camera"]
        main_layout = QVBoxLayout(self)
        form = QFormLayout()

        self.width_box = QSpinBox()
        self.width_box.setRange(160, 7680)
        self.width_box.setValue(int(camera_cfg.get("width", 1920)))
        self.height_box = QSpinBox()
        self.height_box.setRange(120, 4320)
        self.height_box.setValue(int(camera_cfg.get("height", 1080)))
        self.fps_box = QSpinBox()
        self.fps_box.setRange(1, 240)
        self.fps_box.setValue(int(camera_cfg.get("fps", 30)))

        form.addRow("Szerokosc", self.width_box)
        form.addRow("Wysokosc", self.height_box)
        form.addRow("FPS", self.fps_box)

        for name, label in CAMERA_PROPERTY_LABELS.items():
            widget = PropertySlider(name, camera_cfg.get("properties", {}).get(name))
            self.property_widgets[name] = widget
            form.addRow(QLabel(label), widget)

        main_layout.addLayout(form)

        buttons = QHBoxLayout()
        buttons.addStretch(1)
        cancel_button = QPushButton("Anuluj")
        save_button = QPushButton("Zapisz")
        save_button.setDefault(True)
        buttons.addWidget(cancel_button)
        buttons.addWidget(save_button)
        main_layout.addLayout(buttons)

        cancel_button.clicked.connect(self.reject)
        save_button.clicked.connect(self._save)

    def _save(self) -> None:
        self.config["camera"]["width"] = int(self.width_box.value())
        self.config["camera"]["height"] = int(self.height_box.value())
        self.config["camera"]["fps"] = int(self.fps_box.value())
        self.config["camera"]["properties"] = {
            name: widget.value() for name, widget in self.property_widgets.items()
        }
        self.settings_saved.emit(self.config["camera"])
        self.accept()
