#! python3  # noqa: E265

"""RSS dialog widget."""

# standard
from pathlib import Path
from typing import TYPE_CHECKING

# PyQGIS
from qgis.core import Qgis
from qgis.gui import QgsDockWidget, QgsGui
from qgis.PyQt import uic
from qgis.PyQt.QtGui import QImage, QPixmap, QResizeEvent
from qgis.PyQt.QtWidgets import QLabel, QLayout, QScrollBar, QVBoxLayout, QWidget

# Plugin
from oslandia.__about__ import DIR_PLUGIN_ROOT
from oslandia.gui.commons.wdg_label_context_menu import FilterTagLabel
from oslandia.gui.newsfeed.wdg_rss_item import RssItemWidget
from oslandia.newsfeed.rss_reader import RssReader
from oslandia.toolbelt import PlgLogger
from oslandia.toolbelt.preferences import PlgOptionsManager


if TYPE_CHECKING:
    from oslandia.datamodels.mdl_rss_item import RssItem


STYLESHEET_NEWSFEED_TAG_FILTERED = "QLabel{background-color: #3a74ac; border-radius: 10px; color: #ffffff; padding: 1px 2px 1px 2px; margin-right:1px;}"


class RssDockWidget(QgsDockWidget):
    def __init__(self, parent: QWidget | None = None) -> None:
        """Widget to display RSS feed.

        :param parent: parent widget, defaults to None
        :type parent: QObject, optional
        """
        # init module and ui
        super().__init__(parent)
        uic.loadUi(Path(__file__).parent / f"{Path(__file__).stem}.ui", self)

        self.plg_settings = PlgOptionsManager.get_plg_settings()

        # Dock widget on the right
        self.rss_reader = RssReader()
        self.rss: list[RssItem] = self.rss_reader.read_rss()
        self.is_loading = False
        self.nb_cars_allowed = 270

        banner_img = QImage()
        file_path: Path = DIR_PLUGIN_ROOT / "resources/images/banner_rss.png"
        with file_path.open("rb") as f:
            banner_img.loadFromData(f.read())
            banner: QPixmap = QPixmap.fromImage(banner_img)
        self.banner_rss.setPixmap(banner)

        self.init_scrollarea()

        self.rssScrollArea.verticalScrollBar().valueChanged.connect(
            lambda value: self.scrolled(self.rssScrollArea.verticalScrollBar())
        )
        self.load_rss_items()
        self.display_filters()

        instance_gui = QgsGui.instance()
        instance_gui.optionsChanged.connect(self.update_with_plg_settings)

    def init_scrollarea(self) -> None:
        """Initiate the scrollbarlayout and widget"""
        self.container = QWidget()
        self.container.setStyleSheet("background-color: #ffffff")
        self.container_lay = QVBoxLayout(self.container)
        self.rssScrollArea.setWidget(self.container)

    @staticmethod
    def clear_layout(layout: QLayout) -> None:
        """Clear a layout from all added widget

        :param layout: layout to clear
        :type layout: any Qt type layout
        """
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.deleteLater()
                else:
                    layout.removeItem(item)

    def resizeEvent(self, event: QResizeEvent) -> None:  # noqa: N802
        """Update nnumbers of cars available for display description of RSS item

        :param event: resize event
        :type event: QResizeEvent
        """
        self.nb_cars_allowed = int(event.size().width() * 0.6)

        for i in range(self.container_lay.count()):
            rss_item = self.container_lay.itemAt(i).widget()
            if rss_item:
                rss_item.update_description(self.nb_cars_allowed)

        super().resizeEvent(event)

    def load_rss_items(self):
        """Load rss items into the widget"""

        self.is_loading = True

        display_range = 6
        count_loaded_items = self.container_lay.count()
        if count_loaded_items >= len(self.rss):
            return

        stop_ind = count_loaded_items + display_range
        if stop_ind > len(self.rss):
            stop_ind = len(self.rss)

        i = count_loaded_items
        while i < stop_ind:
            if 0 <= i < len(self.rss):
                item = self.rss[i]
                if self.plg_settings.rss_view_only_unread and self.rss_reader.is_read(
                    item
                ):
                    stop_ind += 1
                else:
                    rss_item = RssItemWidget(self)
                    rss_item.qsig_newsfeed_filters_changed.connect(self.update_filters)
                    rss_item.set_item(item, self.nb_cars_allowed)
                    self.container_lay.addWidget(rss_item)
            i += 1

        self.is_loading = False

    def scrolled(self, scrollbar: QScrollBar):
        """Callback for scroll event on the RSS area

        :param scrollbar: QScrollBar, scrollbar object
        """
        if not self.is_loading:
            self.load_rss_items()

    def update_with_plg_settings(self) -> None:
        """Force update of widget with new plugin settings"""
        plg_settings = PlgOptionsManager()
        self.plg_settings = plg_settings.get_plg_settings()
        # Clear the scrollarea
        self.clear_layout(self.container_lay)
        self.rss = self.rss_reader.read_rss()
        self.load_rss_items()
        self.display_filters()

    def update_filters(self, action: str = "add", tag: str = ""):
        """Add or remove tag to filters in settings

        :param add: tells if if it"s and add or remove
        :type add: string
        """
        lowercase_existing_filters = self.plg_settings.get_filters_list(lower=True)
        title_notif = ""
        if action == "add" and tag.lower() not in lowercase_existing_filters:
            # Add a filter
            lowercase_existing_filters.append(tag)
            title_notif = self.tr("Filter added")
        if action == "remove" and tag.lower() in lowercase_existing_filters:
            # Remove a filter
            lowercase_existing_filters.remove(tag.lower())
            title_notif = self.tr("Filter removed")

        PlgOptionsManager.set_value_from_key(
            "rss_category_filters", ",".join(lowercase_existing_filters)
        )

        # Refresh the list
        self.update_with_plg_settings()
        self.display_filters()

        # Notify
        self.log = PlgLogger().log(
            message=f"{title_notif} : {tag}",
            log_level=Qgis.MessageLevel.Info,
            push=True,
            duration=10,
            parent_location=self,
            nb_parent_max_for_message_bar=0,
        )

    def display_filters(self):
        """Display current filters on top of widget"""
        # Display filters
        self.clear_layout(self.filters_lay)
        existing_filters = self.plg_settings.get_filters_list(lower=False)
        if len(existing_filters) > 0:
            text_filters = QLabel()
            text_filters.setText(self.tr("Current filters :"))
            self.filters_lay.addWidget(text_filters)
        for cur_filter in existing_filters:
            tag_filter = FilterTagLabel()
            tag_filter.qsig_tag_filters_changed.connect(self.update_filters)
            tag_filter.setText(cur_filter)
            style = STYLESHEET_NEWSFEED_TAG_FILTERED
            tag_filter.setStyleSheet(style)
            self.filters_lay.addWidget(tag_filter)
