import time
from types import SimpleNamespace

from bec_qthemes import material_icon
from qtpy.QtCore import Property, Qt, Signal
from qtpy.QtGui import QColor
from qtpy.QtWidgets import (
    QDialog,
    QHBoxLayout,
    QLabel,
    QPushButton,
    QSizePolicy,
    QSpacerItem,
    QToolButton,
    QVBoxLayout,
    QWidget,
)

from bec_widgets.utils.colors import get_accent_colors


class LedLabel(QLabel):
    success_led = "color: white;border-radius: 10;background-color: qlineargradient(spread:pad, x1:0.145, y1:0.16, x2:1, y2:1, stop:0 %s, stop:1 %s);"
    emergency_led = "color: white;border-radius: 10;background-color: qlineargradient(spread:pad, x1:0.145, y1:0.16, x2:0.92, y2:0.988636, stop:0 %s, stop:1 %s);"
    warning_led = "color: white;border-radius: 10;background-color: qlineargradient(spread:pad, x1:0.232, y1:0.272, x2:0.98, y2:0.959773, stop:0 %s, stop:1 %s);"
    default_led = "color: white;border-radius: 10;background-color: qlineargradient(spread:pad, x1:0.04, y1:0.0565909, x2:0.799, y2:0.795, stop:0 %s, stop:1 %s);"

    def __init__(self, parent=None):
        super().__init__(parent)

        self.palette = get_accent_colors()
        if self.palette is None:
            # no theme!
            self.palette = SimpleNamespace(
                default=QColor("blue"),
                success=QColor("green"),
                warning=QColor("orange"),
                emergency=QColor("red"),
            )
        self.setState("default")
        self.setFixedSize(20, 20)

    def setState(self, state: str):
        match state:
            case "success":
                r, g, b, a = self.palette.success.getRgb()
                self.setStyleSheet(
                    LedLabel.success_led
                    % (
                        f"rgba({r},{g},{b},{a})",
                        f"rgba({int(r*0.8)},{int(g*0.8)},{int(b*0.8)},{a})",
                    )
                )
            case "default":
                r, g, b, a = self.palette.default.getRgb()
                self.setStyleSheet(
                    LedLabel.default_led
                    % (
                        f"rgba({r},{g},{b},{a})",
                        f"rgba({int(r*0.8)},{int(g*0.8)},{int(b*0.8)},{a})",
                    )
                )
            case "warning":
                r, g, b, a = self.palette.warning.getRgb()
                self.setStyleSheet(
                    LedLabel.warning_led
                    % (
                        f"rgba({r},{g},{b},{a})",
                        f"rgba({int(r*0.8)},{int(g*0.8)},{int(b*0.8)},{a})",
                    )
                )
            case "emergency":
                r, g, b, a = self.palette.emergency.getRgb()
                self.setStyleSheet(
                    LedLabel.emergency_led
                    % (
                        f"rgba({r},{g},{b},{a})",
                        f"rgba({int(r*0.8)},{int(g*0.8)},{int(b*0.8)},{a})",
                    )
                )
            case unknown_state:
                raise ValueError(
                    f"Unknown state {repr(unknown_state)}, must be one of default, success, warning or emergency"
                )


class PopupDialog(QDialog):
    def __init__(self, content_widget):
        self.parent = content_widget.parent()
        self.content_widget = content_widget

        super().__init__(self.parent)

        self.setAttribute(Qt.WA_DeleteOnClose)

        self.content_widget.setParent(self)
        QVBoxLayout(self)
        self.layout().addWidget(self.content_widget)
        self.content_widget.setVisible(True)

    def closeEvent(self, event):
        self.content_widget.setVisible(False)
        self.content_widget.setParent(self.parent)
        self.done(True)


class CompactPopupWidget(QWidget):
    """Container widget, that can display its content or have a compact form,
    in this case clicking on a small button pops the contained widget up.

    In the compact form, a LED-like indicator shows a status indicator.
    """

    expand = Signal(bool)

    def __init__(self, parent=None, layout=QVBoxLayout):
        super().__init__(parent)

        self._popup_window = None
        self._expand_popup = True

        QVBoxLayout(self)
        self.compact_view_widget = QWidget(self)
        self.compact_view_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        QHBoxLayout(self.compact_view_widget)
        self.compact_view_widget.layout().setSpacing(5)
        self.compact_view_widget.layout().setContentsMargins(0, 0, 0, 0)
        self.compact_view_widget.layout().addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Fixed)
        )
        self.compact_label = QLabel(self.compact_view_widget)
        self.compact_status = LedLabel(self.compact_view_widget)
        self.compact_show_popup = QToolButton(self.compact_view_widget)
        self.compact_show_popup.setIcon(
            material_icon(icon_name="expand_content", size=(10, 10), convert_to_pixmap=False)
        )
        self.compact_view_widget.layout().addWidget(self.compact_label)
        self.compact_view_widget.layout().addWidget(self.compact_status)
        self.compact_view_widget.layout().addWidget(self.compact_show_popup)
        self.compact_view_widget.setVisible(False)
        self.layout().addWidget(self.compact_view_widget)
        self.container = QWidget(self)
        self.layout().addWidget(self.container)
        self.container.setVisible(True)
        layout(self.container)
        self.layout = self.container.layout()
        self._compact_view = False

        self.compact_show_popup.clicked.connect(self.show_popup)

    def set_global_state(self, state: str):
        """Set the LED-indicator state

        The LED indicator represents the 'global' state. State can be one of the
        following: "default", "success", "warning", "emergency"
        """
        self.compact_status.setState(state)

    def show_popup(self):
        """Display the contained widgets in a popup dialog"""
        if self._expand_popup:
            # show popup
            self._popup_window = PopupDialog(self.container)
            self._popup_window.show()
            self._popup_window.finished.connect(lambda: self.expand.emit(False))
            self.expand.emit(True)
        else:
            if self.compact_view:
                # expand in place
                self.compact_view = False
                self.compact_view_widget.setVisible(True)
                self.compact_label.setVisible(False)
                self.compact_status.setVisible(False)
                self.compact_show_popup.setIcon(
                    material_icon(
                        icon_name="collapse_content", size=(10, 10), convert_to_pixmap=False
                    )
                )
                self.expand.emit(True)
            else:
                # back to compact form
                self.compact_label.setVisible(True)
                self.compact_status.setVisible(True)
                self.compact_show_popup.setIcon(
                    material_icon(
                        icon_name="expand_content", size=(10, 10), convert_to_pixmap=False
                    )
                )
                self.compact_view = True
                self.expand.emit(False)

    def setSizePolicy(self, size_policy1, size_policy2=None):
        # setting size policy on the compact popup widget will set
        # the policy for the container, and for itself
        if size_policy2 is None:
            # assuming first form: setSizePolicy(QSizePolicy)
            self.container.setSizePolicy(size_policy1)
            QWidget.setSizePolicy(self, size_policy1)
        else:
            self.container.setSizePolicy(size_policy1, size_policy2)
            QWidget.setSizePolicy(self, size_policy1, size_policy2)

    def addWidget(self, widget):
        """Add a widget to the popup container

        The popup container corresponds to the "full view" (not compact)
        The widget is reparented to the container, and added to the container layout
        """
        widget.setParent(self.container)
        self.container.layout().addWidget(widget)

    @Property(bool)
    def compact_view(self):
        return self._compact_view

    @compact_view.setter
    def compact_view(self, set_compact: bool):
        """Sets the compact form

        If set_compact is True, the compact view is displayed ; otherwise,
        the full view is displayed. This is handled by toggling visibility of
        the container widget or the compact view widget.
        """
        self._compact_view = set_compact
        if set_compact:
            self.compact_view_widget.setVisible(True)
            self.container.setVisible(False)
            QWidget.setSizePolicy(self, QSizePolicy.Fixed, QSizePolicy.Fixed)
        else:
            self.compact_view_widget.setVisible(False)
            self.container.setVisible(True)
            QWidget.setSizePolicy(self, self.container.sizePolicy())
        if self.parentWidget():
            self.parentWidget().adjustSize()
        else:
            self.adjustSize()

    @Property(str)
    def label(self):
        return self.compact_label.text()

    @label.setter
    def label(self, compact_label_text: str):
        """Set the label text associated to the compact view"""
        self.compact_label.setText(compact_label_text)

    @Property(str)
    def tooltip(self):
        return self.compact_label.toolTip()

    @tooltip.setter
    def tooltip(self, tooltip: str):
        """Set the tooltip text associated to the compact view"""
        self.compact_label.setToolTip(tooltip)
        self.compact_status.setToolTip(tooltip)

    @Property(bool)
    def expand_popup(self):
        return self._expand_popup

    @expand_popup.setter
    def expand_popup(self, popup: bool):
        self._expand_popup = popup
