import os

import gi
gi.require_version("Gtk", "4.0")
gi.require_version("Pango", "1.0")
from gi.repository import Gtk, GObject, Pango

import stillCenter.constants as constants
import stillCenter.UrlImage as UrlImage

PAGE_SIZE = 50
CARD_WIDTH = 275
CARD_HEIGHT = 84


@Gtk.Template(filename=os.path.join(constants.UI_DIR, "AppGridView.ui"))
class AppGridView(Gtk.FlowBox):
    __gtype_name__ = "AppGridView"
    stillCenter = None

    _model = None
    _offset = 0

    def __init__(self):
        super().__init__()
        self.connect("child-activated", self._on_child_activated)

    # ── card construction ────────────────────────────────────────────────────

    def _make_card(self, item):
        card = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            spacing=15,
            halign=Gtk.Align.FILL,
            valign=Gtk.Align.CENTER,
            hexpand=True,
            vexpand=False,
        )
        card.set_size_request(CARD_WIDTH, CARD_HEIGHT)
        card.add_css_class("card")
        card.add_css_class("app-grid-card")

        icon = UrlImage.UrlImage()
        icon.set_margin_start(5)
        icon.set_margin_top(5)
        icon.set_margin_bottom(5)
        icon.set_halign(Gtk.Align.START)
        icon.set_valign(Gtk.Align.CENTER)
        icon.set_size_request(64, 64)
        card.append(icon)

        text_box = Gtk.Box(
            orientation=Gtk.Orientation.VERTICAL,
            valign=Gtk.Align.CENTER,
            hexpand=True,
            vexpand=False,
            margin_end=10,
        )
        text_box.set_size_request(180, 64)
        card.append(text_box)

        name_label = Gtk.Label(xalign=0)
        name_label.set_wrap(True)
        name_label.set_wrap_mode(Pango.WrapMode.WORD_CHAR)
        name_label.set_ellipsize(Pango.EllipsizeMode.END)
        name_label.set_lines(2)
        name_label.set_width_chars(20)
        name_label.set_max_width_chars(20)
        name_label.set_justify(Gtk.Justification.LEFT)
        name_label.add_css_class("title-4")
        text_box.append(name_label)

        author_label = Gtk.Label(xalign=0, ellipsize=Pango.EllipsizeMode.END, wrap=False, lines=1)
        author_label.set_width_chars(20)
        author_label.set_max_width_chars(20)
        author_label.add_css_class("dim-label")
        text_box.append(author_label)

        flags = GObject.BindingFlags.SYNC_CREATE
        card._bindings = [
            item.bind_property("app-id",        icon,         "app-id",    flags),
            item.bind_property("icon",           icon,         "image-url", flags),
            item.bind_property("name",           name_label,   "label",     flags),
            item.bind_property("author",         author_label, "label",     flags),
            item.bind_property("author-visible", author_label, "visible",   flags),
        ]
        card._app_id = item.app_id
        return card

    def _append_page(self):
        """Append the next PAGE_SIZE items from the model."""
        if self._model is None:
            return
        total = self._model.get_n_items()
        end = min(self._offset + PAGE_SIZE, total)
        for i in range(self._offset, end):
            self.append(self._make_card(self._model.get_item(i)))
        self._offset = end

    # ── signal handlers ──────────────────────────────────────────────────────

    def _on_child_activated(self, _flow_box, child):
        self.stillCenter.app_page.show_app(child.get_child()._app_id)

    # ── public API ───────────────────────────────────────────────────────────

    @property
    def has_more(self):
        return self._model is not None and self._offset < self._model.get_n_items()

    def set_store(self, stillCenter, model):
        self.stillCenter = stillCenter
        self._model = model
        self._offset = 0

        # Remove all existing children
        child = self.get_first_child()
        while child is not None:
            nxt = child.get_next_sibling()
            self.remove(child)
            child = nxt

        self._append_page()

    def load_more(self):
        """Append the next page of items. Called when the user scrolls near the bottom."""
        if self.has_more:
            self._append_page()
