from __future__ import annotations

import os
from pathlib import Path
from typing import Any, cast

import gi

gi.require_version("Gdk", "4.0")
gi.require_version("Gtk", "4.0")
gi.require_version("Gst", "1.0")
from gi.repository import Gdk, Gst, Gtk  # NOQA: E402


class MainWindow(Gtk.ApplicationWindow):
    file_info_label: Gtk.Label

    def __init__(self, *args: Any, **kwargs: Any):
        super().__init__(*args, **kwargs)

        # Make window fullscreen and borderless
        self.set_decorated(False)
        self.fullscreen()

        # Main horizontal box to split the screen
        main_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

        # Create a grid to handle the 1:2 ratio
        grid = Gtk.Grid()
        grid.set_column_homogeneous(True)
        grid.set_hexpand(True)

        # Left third (1/3 width)
        left_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        left_box.set_valign(Gtk.Align.CENTER)
        left_box.set_halign(Gtk.Align.FILL)
        self.file_info_label = Gtk.Label(label="")
        left_box.append(self.file_info_label)

        # Right two-thirds (2/3 width)
        right_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        right_box.set_hexpand(True)

        # Attach boxes to grid with specific column spans
        grid.attach(left_box, 0, 0, 1, 1)
        grid.attach(right_box, 1, 0, 2, 1)

        main_box.append(grid)

        # Create list store and view
        list_store = Gtk.StringList()
        list_view = Gtk.ListView()
        selection_model = Gtk.SingleSelection.new(list_store)
        selection_model.connect("selection-changed", self._on_selection_changed)
        list_view.set_model(selection_model)
        list_view.set_vexpand(True)

        def on_activate(widget: Gtk.ListView, index: int):
            selected_item = selection_model.get_item(index)
            if selected_item:
                string_obj = cast(Gtk.StringObject, selected_item)
                string = string_obj.get_string()
                print("activated", string)

        list_view.connect("activate", on_activate)

        # Factory for list items
        factory = Gtk.SignalListItemFactory()
        factory.connect("setup", self._setup_list_item)
        factory.connect("bind", self._bind_list_item)
        list_view.set_factory(factory)

        # Populate the list store
        self._populate_file_list(list_store)

        # Add list view to a scrolled window
        scrolled = Gtk.ScrolledWindow()
        scrolled.set_child(list_view)
        right_box.append(scrolled)

        self.set_child(main_box)

    def _setup_list_item(self, factory: Gtk.SignalListItemFactory, list_item: Gtk.ListItem):
        label = Gtk.Label()
        label.set_halign(Gtk.Align.START)
        list_item.set_child(label)

    def _bind_list_item(self, factory: Gtk.SignalListItemFactory, list_item: Gtk.ListItem):
        label = cast(Gtk.Label, list_item.get_child())
        item = cast(Gtk.StringObject, list_item.get_item())
        label.set_text(item.get_string())

    def _on_selection_changed(
        self,
        selection_model: Gtk.SingleSelection,
        position: int,
        n_items: int,
    ):
        if selection_model.get_selected() == Gtk.INVALID_LIST_POSITION:
            self.file_info_label.set_text("")
        else:
            selected_item = selection_model.get_selected_item()
            if selected_item:
                string_obj = cast(Gtk.StringObject, selected_item)
                self.file_info_label.set_text(string_obj.get_string())

    def _populate_file_list(self, list_store: Gtk.StringList) -> None:
        # TODO: Implement proper version sort (strverscmp equivalent)

        directories: list[str] = ["../"]
        files: list[str] = []

        with os.scandir(".") as it:
            for entry in it:
                if entry.name == ".." or not entry.name.startswith("."):
                    if entry.is_dir():
                        directories.append(entry.name + "/")
                    else:
                        files.append(entry.name)

        directories.sort(key=lambda x: x.lower())
        files.sort(key=lambda x: x.lower())

        while list_store.get_n_items():
            list_store.remove(0)

        for name in directories + files:
            list_store.append(name)

        all = directories + files
        self.file_info_label.set_text(all[0] if all else "")


class App(Gtk.Application):
    def __init__(self):
        super().__init__()

        # Initialize GStreamer
        Gst.init(None)

        # Load CSS
        css_provider = Gtk.CssProvider()
        css_file = Path(__file__).parent / "style.css"
        css_provider.load_from_path(str(css_file))

        display = Gdk.Display.get_default()
        if display is None:
            raise RuntimeError("No display available")

        Gtk.StyleContext.add_provider_for_display(
            display,
            css_provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,
        )

    def do_activate(self):
        win = MainWindow(application=self)
        win.present()


def main():
    app = App()
    app.run(None)