# standard
from pathlib import Path
from typing import Optional

# PyQGIS
from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QCursor, QIcon, QMouseEvent, QPixmap
from qgis.PyQt.QtWidgets import QLabel, QWidget

from oslandia.gui.stylesheet import BACKGROUND_BLACK_SEMI_TRANSPARENT, WidgetStyleSheet


class WdgImageList(WidgetStyleSheet):
    def __init__(self, parent: Optional[QWidget] = None) -> None:
        """Widget to display list of images

        :param parent: parent widget, defaults to None
        :type parent: Optional[QWidget], optional
        """
        super().__init__(parent)
        uic.loadUi(Path(__file__).parent / f"{Path(__file__).stem}.ui", self)

        self.btn_next.clicked.connect(self.next)
        self.btn_prev.clicked.connect(self.prev)
        self.btn_next.setIcon(QIcon(":images/themes/default/mActionArrowRight.svg"))
        self.btn_prev.setIcon(QIcon(":images/themes/default/mActionArrowLeft.svg"))
        self.btn_next.setCursor(Qt.CursorShape.PointingHandCursor)
        self.btn_prev.setCursor(Qt.CursorShape.PointingHandCursor)

    def next(self) -> None:
        """Display next image"""
        cur_index = self.stackedWidget.currentIndex()
        if cur_index < self.stackedWidget.count():
            self.stackedWidget.setCurrentIndex(cur_index + 1)
        self._update_button_status()

    def prev(self) -> None:
        """Display previous image"""
        cur_index = self.stackedWidget.currentIndex()
        if cur_index != 0:
            self.stackedWidget.setCurrentIndex(cur_index - 1)
        self._update_button_status()

    def _update_button_status(self) -> None:
        """Update button status from current stacked index"""
        self.btn_next.setEnabled(
            self.stackedWidget.currentIndex() != self.stackedWidget.count() - 1
        )
        self.btn_prev.setEnabled(self.stackedWidget.currentIndex() != 0)

    def set_image_list(
        self, image_path_list: list[Path], display_name: Optional[str] = None
    ) -> None:
        """Defined displayed image list

        :param image_path_list: image file paths
        :type image_path_list: list[Path]
        :param display_name: display name for large image show
        :type display_name: Optional[str]
        """
        # Remove all inserted images
        while self.stackedWidget.count():
            self.stackedWidget.removeWidget(self.stackedWidget.widget(0))

        # Add label for all images
        for image_path in image_path_list:
            lbl_image = QLabel()
            # Display image if it exists
            if image_path.exists():
                name = display_name
                if name is None:
                    name = str(image_path)

                image = QPixmap(str(image_path))
                lbl_image.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
                image_small = image.scaled(
                    600,
                    300,
                    Qt.AspectRatioMode.KeepAspectRatio,
                    Qt.TransformationMode.SmoothTransformation,
                )
                lbl_image.setPixmap(image_small)
                lbl_image.setAlignment(Qt.AlignmentFlag.AlignCenter)

                # Display large image with mousePressEvent
                lbl_image.mousePressEvent = lambda event, name=name, image=image: (
                    self.show_large_image(event, name=name, image=image)
                )
            # Display message if image doesn't exists
            else:
                lbl_image.setText(self.tr("Image {} not available.").format(image_path))

            # Add label
            self.stackedWidget.insertWidget(self.stackedWidget.count(), lbl_image)

        nb_image = self.stackedWidget.count()
        self.btn_next.setVisible(nb_image > 1)
        self.btn_prev.setVisible(nb_image > 1)
        self.btn_next.setEnabled(nb_image > 1)
        self.btn_prev.setEnabled(False)
        if nb_image != 0:
            self.stackedWidget.setCurrentIndex(0)

    def show_large_image(
        self,
        event: QMouseEvent,
        name: str,
        image: QPixmap,
        max_size_ratio: float = 0.75,
    ) -> None:
        """Display a full-size image as an overlay inside the top-level window.

        :param name: Name of the image (unused in overlay mode)
        :type name: str
        :param image: Image to display
        :type image: QPixmap
        """
        top = self.window()

        # Limit image size to 75% of the window containing the widget
        max_size = top.size() * max_size_ratio
        if image.width() > max_size.width() or image.height() > max_size.height():
            image = image.scaled(
                max_size,
                Qt.AspectRatioMode.KeepAspectRatio,
                Qt.TransformationMode.SmoothTransformation,
            )

        overlay = QLabel(top)
        overlay.setPixmap(image)
        overlay.setAlignment(Qt.AlignmentFlag.AlignCenter)
        overlay.setStyleSheet(BACKGROUND_BLACK_SEMI_TRANSPARENT)
        overlay.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        overlay.setGeometry(top.rect())
        overlay.mousePressEvent = lambda e: overlay.deleteLater()
        overlay.show()
        overlay.raise_()

    def clear(self) -> None:
        """Remove all images and hide navigation buttons"""
        while self.stackedWidget.count():
            self.stackedWidget.removeWidget(self.stackedWidget.widget(0))

        self.btn_next.setVisible(False)
        self.btn_prev.setVisible(False)
