import logging

from PyQt6.QtWidgets import QFormLayout, QComboBox, QPushButton, QSlider, QHBoxLayout, QCheckBox
from PyQt6.QtCore import Qt
from Model.ESP32Cam import ESP32Cam

class CameraSettingsPanel(QFormLayout):
    """
    Class to create a camera settings panel for the ESP32 camera.
    """

    def __init__(self):
        super().__init__()

        self.cameras = []

        # << -- Camera ID Selector -- >>
        self.camera_id_combobox = QComboBox()
        self.camera_id_combobox.setPlaceholderText("Select Camera")
        self.camera_id_combobox.currentIndexChanged.connect(self._on_camera_id_changed)

        #  << -- Camera Resolution Selector -- >>
        self.camera_resolution_combobox = QComboBox()
        
        # << -- Camera Bightness Selector -- >>
        self.camera_brightness_slider = QSlider()
        self.camera_brightness_slider.setOrientation(Qt.Orientation.Horizontal)

        # << -- Camera Contrast Selector -- >>
        self.camera_contrast_slider = QSlider()
        self.camera_contrast_slider.setOrientation(Qt.Orientation.Horizontal)
        
        # << -- Camera Saturation Selector -- >>
        self.camera_saturation_slider = QSlider()
        self.camera_saturation_slider.setOrientation(Qt.Orientation.Horizontal)

        # << -- Camera Exposure Selector  -- >>
        self.exposure_layout = QHBoxLayout()
        self.camera_auto_exposure_checkbox = QCheckBox("Auto")
        self.camera_exposure_slider = QSlider()
        self.camera_exposure_slider.setOrientation(Qt.Orientation.Horizontal)
        self.camera_auto_exposure_checkbox.setChecked(True)
        self.exposure_layout.addWidget(self.camera_auto_exposure_checkbox)
        self.exposure_layout.addWidget(self.camera_exposure_slider)

        # << -- Camera Gain Selector -- >>
        self.gain_layout = QHBoxLayout()
        self.camera_auto_gain_checkbox = QCheckBox("Auto")
        self.camera_gain_slider = QSlider()
        self.camera_gain_slider.setOrientation(Qt.Orientation.Horizontal)
        self.camera_auto_gain_checkbox.setChecked(True)
        self.gain_layout.addWidget(self.camera_auto_gain_checkbox)
        self.gain_layout.addWidget(self.camera_gain_slider)

        # << -- Camera Flip Selector -- >>
        self.flip_layout = QHBoxLayout()
        self.camera_horizontal_flip_checkbox = QCheckBox("Horizontal")
        self.camera_vertical_flip_checkbox = QCheckBox("Vertical")
        self.flip_layout.addWidget(self.camera_horizontal_flip_checkbox)
        self.flip_layout.addWidget(self.camera_vertical_flip_checkbox)

        # << -- Camera Flash Selector -- >>
        self.flash_checkbox = QCheckBox()
        self.flash_checkbox.setChecked(False)

        # << -- Camera Configure Button -- >>
        self.camera_settings_button = QPushButton("Apply")

        # << -- Set the rows in the form layout -- >>
        self.addRow("Camera ID:", self.camera_id_combobox)
        self.addRow("Resolution:", self.camera_resolution_combobox)
        self.addRow("Brightness:", self.camera_brightness_slider)
        self.addRow("Contrast:", self.camera_contrast_slider)
        self.addRow("Saturation:", self.camera_saturation_slider)
        self.addRow("Exposure:", self.exposure_layout)
        self.addRow("Gain:", self.gain_layout)
        self.addRow("Flip:", self.flip_layout)
        self.addRow("Flash LED:", self.flash_checkbox)
        self.addRow(self.camera_settings_button)

        self.hide_camera_settings() # Hide the camera configuration by default


    def hide_camera_settings(self) -> None:
        """Hide the camera settings in the form layout."""
        self.setRowVisible(self.camera_settings_button, False)
        self.setRowVisible(self.camera_resolution_combobox, False)
        self.setRowVisible(self.camera_brightness_slider, False)
        self.setRowVisible(self.camera_contrast_slider, False)
        self.setRowVisible(self.camera_saturation_slider, False)
        self.setRowVisible(self.exposure_layout, False)
        self.setRowVisible(self.gain_layout, False)
        self.setRowVisible(self.flip_layout, False)
        self.setRowVisible(self.flash_checkbox, False)


    def show_camera_settings(self) -> None:
        """Show the camera settings in the form layout."""
        self.setRowVisible(self.camera_settings_button, True)
        self.setRowVisible(self.camera_resolution_combobox, True)
        self.setRowVisible(self.camera_brightness_slider, True)
        self.setRowVisible(self.camera_contrast_slider, True)
        self.setRowVisible(self.camera_saturation_slider, True)
        self.setRowVisible(self.exposure_layout, True)
        self.setRowVisible(self.gain_layout, True)
        self.setRowVisible(self.flip_layout, True)
        self.setRowVisible(self.flash_checkbox, True)

    
    def update_camera_id_combobox(self, cameras: list[ESP32Cam]) -> None:
        """Update the camera id combobox with the list of cameras."""
        self._cameras = cameras
        self.camera_id_combobox.clear()
        self.camera_id_combobox.addItem("Select Camera", None)
        for camera in cameras:
            self.camera_id_combobox.addItem("ESP32CAM-" + camera.id, camera.id)
    

    def get_selected_camera_id(self) -> str:
        """Get the selected camera id from the combobox."""
        return self.camera_id_combobox.currentData()

    def _on_camera_id_changed(self, index: int) -> None:
        camera_id = self.camera_id_combobox.currentData()
        for camera in self._cameras:
            if camera.id == camera_id:
                self._set_camera_settings(camera)
                self.show_camera_settings()
                logging.info(f"Camera ID changed to {camera_id}")
                return
        self.hide_camera_settings()


    def _set_camera_settings(self, camera: ESP32Cam) -> None:
        """Set the camera settings in the form layout."""
        self.camera_resolution_combobox.clear()
        self.camera_resolution_combobox.addItems([str(res) for res in camera.get_resolutions()])
        self.camera_resolution_combobox.setCurrentText(str(camera.resolution))
        self.camera_brightness_slider.setMinimum(camera.MIN_BRIGHTNESS)
        self.camera_brightness_slider.setMaximum(camera.MAX_BRIGHTNESS)
        self.camera_brightness_slider.setValue(camera.brightness)
        self.camera_contrast_slider.setMinimum(camera.MIN_CONTRAST)
        self.camera_contrast_slider.setMaximum(camera.MAX_CONTRAST)
        self.camera_contrast_slider.setValue(camera.contrast)
        self.camera_saturation_slider.setMinimum(camera.MIN_SATURATION)
        self.camera_saturation_slider.setMaximum(camera.MAX_SATURATION)
        self.camera_saturation_slider.setValue(camera.saturation)
        self.camera_auto_exposure_checkbox.setChecked(camera.automatic_exposure)
        self.camera_exposure_slider.setMinimum(camera.MIN_EXPOSURE)
        self.camera_exposure_slider.setMaximum(camera.MAX_EXPOSURE)
        self.camera_exposure_slider.setValue(camera.exposure)
        self.camera_auto_gain_checkbox.setChecked(camera.automatic_gain)
        self.camera_gain_slider.setMinimum(camera.MIN_GAIN)
        self.camera_gain_slider.setMaximum(camera.MAX_GAIN)
        self.camera_gain_slider.setValue(camera.gain)
        self.camera_vertical_flip_checkbox.setChecked(camera.vertical_flip)
        self.camera_horizontal_flip_checkbox.setChecked(camera.horizontal_flip)

    def get_camera_settings(self) -> dict[str, str | int | bool]:
        """Get the camera settings from the form layout."""
        camera_settings = {
            "camera_id": self.camera_id_combobox.currentData(),
            "frame_size": self.camera_resolution_combobox.currentText(),
            "brightness": self.camera_brightness_slider.value(),
            "contrast": self.camera_contrast_slider.value(),
            "saturation": self.camera_saturation_slider.value(),
            "exposure_value": self.camera_exposure_slider.value(),
            "auto_exposure": self.camera_auto_exposure_checkbox.isChecked(),
            "gain_value": self.camera_gain_slider.value(),
            "auto_gain": self.camera_auto_gain_checkbox.isChecked(),
            "horizontal_flip": self.camera_horizontal_flip_checkbox.isChecked(),
            "vertical_flip": self.camera_vertical_flip_checkbox.isChecked(),
            "led_on": self.flash_checkbox.isChecked()
        }
        return camera_settings
    
    
    def get_current_camera_id(self) -> str:
        """Get the current camera id from the combobox."""
        return self.camera_id_combobox.currentData()


