import os
from pathlib import Path
from pywayland.client import Display
from pywayland.protocol.wayland import WlRegistry
from pywayland.protocol.wlr_foreign_toplevel_management_unstable_v1 import (
    ZwlrForeignToplevelManagerV1,
    ZwlrForeignToplevelHandleV1
)
import panorama_panel

import gi

gi.require_version("Gtk", "4.0")

from gi.repository import Gtk, GLib, Gio, Gdk


module_directory = Path(__file__).resolve().parent


class WindowButton(Gtk.ToggleButton):
    def __init__(self, window_id, window_title, **kwargs):
        super().__init__(**kwargs)

        self.window_id = window_id
        self.window_title = window_title
        self.set_has_frame(False)

        self.set_label(self.window_title)

        self.last_state = False


class WFWindowList(panorama_panel.Applet):
    name = "Wayfire window list"
    description = "Traditional window list (for Wayfire)"

    def __init__(self, orientation=Gtk.Orientation.HORIZONTAL, config=None):
        super().__init__(orientation=orientation, config=config)
        if config is None:
            config = {}

        self.toplevel_buttons: dict[ZwlrForeignToplevelHandleV1, WindowButton] = {}
        # This button doesn't belong to any window but is used for the button group and to be
        # selected when no window is focused
        self.initial_button = Gtk.ToggleButton()

        self.display = Display()
        self.display.connect()
        self.registry = self.display.get_registry()
        self.registry.dispatcher["global"] = self.on_global
        self.display.roundtrip()
        fd = self.display.get_fd()
        GLib.io_add_watch(fd, GLib.IO_IN, self.on_display_event)

        self.context_menu = self.make_context_menu()
        panorama_panel.track_popover(self.context_menu)

        right_click_controller = Gtk.GestureClick()
        right_click_controller.set_button(3)
        right_click_controller.connect("pressed", self.show_context_menu)

        self.add_controller(right_click_controller)

        action_group = Gio.SimpleActionGroup()
        options_action = Gio.SimpleAction.new("options", None)
        options_action.connect("activate", self.show_options)
        action_group.add_action(options_action)
        self.insert_action_group("applet", action_group)

        self.options_window = None

    def on_display_event(self, source, condition):
        if condition == GLib.IO_IN:
            self.display.dispatch(block=True)
        return True

    def on_global(self, registry, name, interface, version):
        print(f"Global: {interface} (v{version})")
        if interface == "zwlr_foreign_toplevel_manager_v1":
            print("Interface registered")
            self.manager = registry.bind(name, ZwlrForeignToplevelManagerV1, version)
            self.manager.dispatcher["toplevel"] = self.on_new_toplevel
            self.manager.dispatcher["finished"] = lambda *a: print("Toplevel manager finished")
            self.display.roundtrip()
            self.display.flush()

    def on_new_toplevel(self, manager: ZwlrForeignToplevelManagerV1,
                         handle: ZwlrForeignToplevelHandleV1):
        print("Toplevel received")
        handle.dispatcher["title"] = lambda h, title: self.on_title_changed(h, title)
        #handle.dispatcher["app_id"] = lambda h, app_id: self.on_app_id_changed(h, app_id)
        #handle.dispatcher["state"] = lambda h, states: self.on_state_changed(h, states)
        #handle.dispatcher["closed"] = lambda h: self.on_closed(h)

    def on_title_changed(self, handle, title):
        print(f"Window title: {title}")
        if handle not in self.toplevel_buttons:
            button = WindowButton(id(handle), title)
            button.set_group(self.initial_button)
            button.connect("clicked", lambda *a: self.on_button_click(handle))
            self.toplevel_buttons[handle] = button
            self.append(button)

    def make_context_menu(self):
        menu = Gio.Menu()
        menu.append("Window list _options", "applet.options")
        context_menu = Gtk.PopoverMenu.new_from_model(menu)
        context_menu.set_has_arrow(False)
        context_menu.set_parent(self)
        context_menu.set_halign(Gtk.Align.START)
        context_menu.set_flags(Gtk.PopoverMenuFlags.NESTED)
        return context_menu

    def show_context_menu(self, gesture, n_presses, x, y):
        rect = Gdk.Rectangle()
        rect.x = int(x)
        rect.y = int(y)
        rect.width = 1
        rect.height = 1

        self.context_menu.set_pointing_to(rect)
        self.context_menu.popup()

    def show_options(self, _0=None, _1=None):
        pass

    def get_config(self):
        return {}
