import os
import sys

from PyQt6.QtWidgets import QGroupBox, QFormLayout, QLineEdit, QPushButton, QHBoxLayout, QCheckBox, QFileDialog
from PyQt6.QtGui import QRegularExpressionValidator, QIcon
from PyQt6.QtCore import QRegularExpression



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

class MQTTGroup(QGroupBox):
    """
    MQTTGroup is a class that represents a group of widgets for configuring the MQTT settings.
    """
    
    def __init__(self, title: str):
        super().__init__(title)
        
        # << -- MQTT Broker Setup -- >>
        self._broker_ip_edit = QLineEdit()
        self._broker_port_edit = QLineEdit()
        self._broker_ip_edit.setPlaceholderText("127.0.0.1")
        self._broker_port_edit.setPlaceholderText("1883")
        self._broker_ip_edit.setValidator(QRegularExpressionValidator(QRegularExpression(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")))
        self._broker_port_edit.setValidator(QRegularExpressionValidator(QRegularExpression(r"^\d{1,5}$")))

        # << -- MQTT Credentials Setup -- >>
        self._use_credentials_checkbox = QCheckBox()
        self._username_edit = QLineEdit()
        self._password_edit = QLineEdit()
        self._password_button = QPushButton()
        self._password_layout = QHBoxLayout()
        self._password_edit.setEchoMode(QLineEdit.EchoMode.Password)
        self._password_button.setCheckable(True)
        self._password_button.setMaximumSize(30, 30)
        self._password_button.setIcon(QIcon(f"{ASSETS_DIR}/show.png"))
        self._use_credentials_checkbox.checkStateChanged.connect(self._toggle_credentials_options)
        self._password_button.clicked.connect(self._switch_password_echo_mode)
        self._password_layout.addWidget(self._password_edit)
        self._password_layout.addWidget(self._password_button)

        # << -- MQTT TLS Setup -- >>
        self._tls_checkbox = QCheckBox()
        self._tls_checkbox.checkStateChanged.connect(self._toggle_tls_options)
        self._tls_button = QPushButton("Select certificate")
        self._tls_button.clicked.connect(self._select_tls_certificate)
        self._tls_path = None

        # << -- MQTT Form Setup -- >>
        self._layout = QFormLayout()
        self._layout.addRow("Broker IP", self._broker_ip_edit)
        self._layout.addRow("Broker Port", self._broker_port_edit)
        self._layout.addRow("Require credentials", self._use_credentials_checkbox) 
        self._layout.addRow("    Username", self._username_edit)
        self._layout.addRow("    Password", self._password_layout)
        self._layout.addRow("Use TLS", self._tls_checkbox)
        self._layout.addRow("    Certificate", self._tls_button)
        self._layout.setRowVisible(self._username_edit, False)
        self._layout.setRowVisible(self._password_layout, False)
        self._layout.setRowVisible(self._tls_button, False)

        # << -- MQTT Layout Setup -- >>
        self.setLayout(self._layout)


    @property
    def broker_ip(self) -> str:
        return self._broker_ip_edit.text().strip()
    
    @broker_ip.setter
    def broker_ip(self, ip: str) -> None:
        self._broker_ip_edit.setText(ip)

    @property
    def broker_port(self) -> int:
        try:
            return int(self._broker_port_edit.text().strip())
        except ValueError:
            return 0
        
    @broker_port.setter
    def broker_port(self, port: int) -> None:
        self._broker_port_edit.setText(str(port))

    @property
    def use_credentials(self) -> bool:
        return self._use_credentials_checkbox.isChecked()
    
    @use_credentials.setter
    def use_credentials(self, use: bool) -> None:
        self._use_credentials_checkbox.setChecked(use)
        self._toggle_credentials_options()

    @property
    def username(self) -> str | None:
        if not self._use_credentials_checkbox.isChecked():
            return None
        return self._username_edit.text().strip()
    
    @username.setter
    def username(self, username: str) -> None:
        self._username_edit.setText(username)

    @property
    def tls_path(self) -> str|None:
        if not self._tls_checkbox.isChecked():
            return ""
        return self._tls_path
    
    @property
    def tls_enabled(self) -> bool:
        return self._tls_checkbox.isChecked()
    
    @tls_enabled.setter
    def tls_enabled(self, enabled: bool) -> None:
        self._tls_checkbox.setChecked(enabled)
        self._toggle_tls_options()

    @tls_path.setter
    def tls_path(self, path: str) -> None:
        self._tls_path = path
        file_name = path.split("/")[-1]
        self._tls_button.setText("(" + file_name + ")")

    @property
    def password(self) -> str|None:
        if not self._use_credentials_checkbox.isChecked():
            return None
        return self._password_edit.text().strip()

    def _switch_password_echo_mode(self):
        """Switches the echo mode of the password edit field between normal and password."""
        if self._password_button.isChecked():
            self._password_edit.setEchoMode(QLineEdit.EchoMode.Normal)
            self._password_button.setIcon(QIcon(f"{ASSETS_DIR}/hide.png"))
        else:
            self._password_edit.setEchoMode(QLineEdit.EchoMode.Password)
            self._password_button.setIcon(QIcon(f"{ASSETS_DIR}/show.png"))


    def _toggle_credentials_options(self):
        """Show or hide the credentials options based on the checkbox state."""
        if self._use_credentials_checkbox.isChecked():
            self._layout.setRowVisible(self._username_edit, True)
            self._layout.setRowVisible(self._password_layout, True)
        else:
            self._layout.setRowVisible(self._username_edit, False)
            self._layout.setRowVisible(self._password_layout, False)

        
    def _toggle_tls_options(self):
        """Show or hide the TLS options based on the checkbox state."""
        if self._tls_checkbox.isChecked():
            self._layout.setRowVisible(self._tls_button, True)
        else:
            self._layout.setRowVisible(self._tls_button, False)


    def _select_tls_certificate(self):
        """Open a file dialog to select the TLS certificate."""
        self._tls_path = QFileDialog.getOpenFileName(self, "Select certificate", "", "Certificate files (*.crt *.pem)")[0]
        if self._tls_path:
            file_name = self._tls_path.split("/")[-1]
            self._tls_button.setText("(" + file_name + ")")
