
import os, sys

from PyQt6.QtWidgets import QWidget, QVBoxLayout, QCheckBox, QLabel, QPushButton, QMessageBox

from ui.WifiGroup import WifiGroup
from ui.MQTTGroup import MQTTGroup
from ui.LoadingPopup import LoadingPopup
from utils.ConfigureThread import ConfigureThread
from utils.config import get_config, save_config, is_config_exists, delete_config

if getattr(sys, 'frozen', False):
    ASSETS_DIR = os.path.join(sys._MEIPASS, "assets") 
else: 
    ASSETS_DIR = os.path.dirname(os.path.abspath(__file__)) + "/../assets"


class MainView(QWidget):
    """
    Main view of the application. This class is responsible for displaying the main window and handling the configuration of the ESP32-CAM.
    """
    def __init__(self) -> None:
        super().__init__()
        
        # << -- Window setup -- >>
        self.setWindowTitle("Configure the system")
        self.setGeometry(100, 100, 400, 480)
        self.setMaximumSize(400, 480)
        self.setMinimumSize(400, 480)

        # << -- Widgets setup -- >>
        self.wifi_group = WifiGroup("Wi-Fi Configuration")
        self.mqtt_group = MQTTGroup("MQTT Configuration")
        self.remember_checkbox = QCheckBox("Remember")
        self.wifi_warning_label = QLabel("⚠  Remember to connect to the ESP32's WiFi network (click the help button for more information)")
        self.help_button = QPushButton("❓ Help")
        self.save_button = QPushButton("⚙️ Configure")
        self.help_button.setStyleSheet("background-color: orange")
        self.save_button.setStyleSheet("background-color: #3498db")
        self.remember_checkbox.setChecked(False)
        self.wifi_warning_label.setWordWrap(True)
        
        # << -- Callbacks setup -- >>
        self.save_button.clicked.connect(self._configure_camera)
        self.help_button.clicked.connect(self._show_help_info)

        # << -- Layout setup -- >>
        self.main_layout = QVBoxLayout()
        self.main_layout.addWidget(self.wifi_group)
        self.main_layout.addWidget(self.mqtt_group)
        self.main_layout.addWidget(self.remember_checkbox)
        self.main_layout.addWidget(self.wifi_warning_label)
        self.main_layout.addWidget(self.help_button)
        self.main_layout.addWidget(self.save_button)
        self.setLayout(self.main_layout)

        # << -- Load initial values -- >>
        self._load_initial_values()


    def _load_initial_values(self) -> None:
        """
        Load the initial values for the form fields
        """
        if is_config_exists():
            config = get_config()
            
            self.remember_checkbox.setChecked(True)
            self.wifi_group.wifi_ssid = config["wifi_ssid"]
            self.mqtt_group.broker_ip = config["broker_ip"]
            self.mqtt_group.broker_port = config["broker_port"]
            if config["broker_username"]:
                self.mqtt_group.use_credentials = True
                self.mqtt_group.username = config["broker_username"]

            if config["mqtt_cert_path"]:
                self.mqtt_group.tls_enabled = True
                self.mqtt_group._tls_path = config["mqtt_cert_path"]
                

    def _configure_camera(self) -> None:
        """
        Callback for the configure button click
        """
        wifi_ssid = self.wifi_group.wifi_ssid
        wifi_password = self.wifi_group.wifi_password
        broker_ip = self.mqtt_group.broker_ip
        broker_port = self.mqtt_group.broker_port
        broker_username = self.mqtt_group.username
        broker_password = self.mqtt_group.password
        mqtt_cert = self.mqtt_group.tls_path  

        if self._validate_fields(wifi_ssid, wifi_password, broker_ip, broker_port, broker_username, broker_password, mqtt_cert):
            self.loading_popup = LoadingPopup("Configuring...", self)
            self.loading_popup.show()
            if self.remember_checkbox.isChecked():
                save_config(wifi_ssid, broker_ip, broker_port, broker_username, mqtt_cert)
            else:
                delete_config()

            self._configure_thread = ConfigureThread(wifi_ssid, wifi_password, broker_ip, broker_port, broker_username, broker_password, mqtt_cert)
            self._configure_thread.error.connect(self._on_configure_error)
            self._configure_thread.finished.connect(self._on_configure_finished)
            self._configure_thread.start()
            

    def _on_configure_error(self, error: str) -> None:
        """
        Callback for the configure error signal
        """
        self.loading_popup.close()
        QMessageBox.critical(self, "Error", "Cannot connect to ESP32. \nPlease ensure that you are connected to ESP32-CAM's Wi-Fi network")


    def _on_configure_finished(self, success: bool) -> None:
        """
        Callback for the configure finished signal
        """
        self.loading_popup.close()
        if success:
            QMessageBox.information(self, "Success", "Camera configured successfully")
        else:
            QMessageBox.critical(self, "Error", "Error configuring the camera. Please try again.")


    def _validate_fields(self, wifi_ssid: str, wifi_password: str, broker_ip: str, broker_port: int, broker_username: str, broker_password: str, mqtt_cert_path: str) -> bool:
        """
        Validate the fields in the form
        """
        if not broker_ip:
            message = "Please fill broker IP"  
        elif not broker_port:
            message = "Please fill broker port"
        elif not wifi_ssid:
            message = "Please fill Wi-Fi SSID"
        elif not wifi_password:
            message = "Please fill Wi-Fi password"
        elif self.mqtt_group.use_credentials and not broker_username:
            message = "Please fill broker username"
        elif self.mqtt_group.use_credentials and not broker_password:
            message = "Please fill broker password"
        elif self.mqtt_group.tls_enabled and not mqtt_cert_path:
            message = "Please select a TLS certificate"
        else:
            return True
        QMessageBox.critical(self, "Error", message)
        return False
        

    def _show_help_info(self) -> None:
        """
        Callback for the help button click
        """
        text = "➤ This configuration window allows you to configure the Wi-Fi and MQTT broker credentials, so that the ESP32-CAM can connect and this application can work properly.\n\n\n"
        text += "⚠️ In order to apply the configuration correctly, it is important that you first connect to the Wi-Fi network provided by the microcontroller:\n\n"
        text += "    • SSID: ESP32-CAM\n"
        text += "    • Password: BGARGJtd\n\n\n"
        text += "➤ After configuring, the program will automatically connect you and the microcontroller to the specified Wi-Fi network and MQTT broker."
        QMessageBox.information(self, "Help", text)
        
        