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

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


class Applet(Gtk.Box):
    name = "Generic applet"
    description = ""

    def __init__(self, orientation=Gtk.Orientation.HORIZONTAL, config=None):
        super().__init__(orientation=orientation)
        if orientation == Gtk.Orientation.VERTICAL:
            self.set_hexpand(True)
            self.set_vexpand(False)
        elif orientation == Gtk.Orientation.HORIZONTAL:
            self.set_vexpand(True)
            self.set_hexpand(False)

        self.drag_source = Gtk.DragSource(actions=Gdk.DragAction.MOVE)
        self.drag_source.connect("prepare", self.provide_drag_data)
        self.drag_source.connect("drag-begin", self.drag_begin)
        self.drag_source.connect("drag-cancel", self.drag_cancel)

    def provide_drag_data(self, source: Gtk.DragSource, x: float, y: float):
        app = self.get_root().get_application()
        app.drags[id(self)] = self
        value = GObject.Value()
        value.init(GObject.TYPE_UINT64)
        value.set_uint64(id(self))
        print(value)
        return Gdk.ContentProvider.new_for_value(value)

    def drag_begin(self, source: Gtk.DragSource, drag: Gdk.Drag):
        paintable = Gtk.WidgetPaintable.new(self).get_current_image()
        source.set_icon(paintable, 0, 0)
        self.hide()

    def drag_cancel(self, source: Gtk.DragSource, drag: Gdk.Drag, reason: Gdk.DragCancelReason):
        self.show()
        return False

    def get_config(self):
        return {}

    def set_panel_position(self, position: Gtk.PositionType):
        return

    def make_draggable(self):
        self.add_controller(self.drag_source)

    def restore_drag(self):
        self.remove_controller(self.drag_source)

    def track_popover(self, popover: Gtk.Popover):
        popover.connect("show", lambda *args: _popover_shown(self, popover))
        popover.connect("closed", lambda *args: _popover_hidden(self, popover))

def track_popover(popover: Gtk.Popover):
    popover.connect("show", lambda *args: _popover_shown(None, popover))
    popover.connect("closed", lambda *args: _popover_hidden(None, popover))


def _popover_shown(applet, popover: Gtk.Popover):
    popover.get_root().open_popovers.add(id(popover))
    if popover.get_root().autohide:
        GLib.timeout_add(popover.get_root().hide_time // (popover.get_root().size - 1),
                         popover.get_root().slide_in)


def _popover_hidden(applet, popover: Gtk.Popover):
    popover.get_root().open_popovers.remove(id(popover))
    if popover.get_root().autohide and not popover.get_root().open_popovers:
        GLib.timeout_add(popover.get_root().hide_time // (popover.get_root().size - 1),
                         popover.get_root().slide_out)


def get_panel_position(applet: Applet) -> Gtk.PositionType:
    return applet.get_root().position


OPPOSITE_POSITION = {
    Gtk.PositionType.TOP: Gtk.PositionType.BOTTOM,
    Gtk.PositionType.BOTTOM: Gtk.PositionType.TOP,
    Gtk.PositionType.LEFT: Gtk.PositionType.RIGHT,
    Gtk.PositionType.RIGHT: Gtk.PositionType.LEFT,
}

POSITION_TO_ARROW = {
    Gtk.PositionType.TOP: Gtk.ArrowType.UP,
    Gtk.PositionType.BOTTOM: Gtk.ArrowType.DOWN,
    Gtk.PositionType.LEFT: Gtk.ArrowType.LEFT,
    Gtk.PositionType.RIGHT: Gtk.ArrowType.RIGHT,
}
