from gi.repository import Gtk


def update_action_widget_visibility(widgets, visible_predicate):
    """This sets the visibility on a set of widgets, like menu items. You provide a function
    that indicates if an item is visible, or None for separators that are visible based on
    their neighbors. Returns the count of visible widgets that are not separators."""
    visible_count = 0
    previous_visible_widget = None
    for w in widgets:
        visible = visible_predicate(w)

        if visible:
            visible_count = visible_count + 1

        if visible is None:
            if previous_visible_widget is None:
                visible = False
            else:
                visible = visible_predicate(previous_visible_widget) is not None

        w.set_visible(visible)
        if visible:
            previous_visible_widget = w

    if previous_visible_widget and visible_predicate(previous_visible_widget) is None:
        previous_visible_widget.set_visible(False)
    return visible_count


class ContextualMenu(Gtk.Menu):
    def __init__(self, main_entries):
        super().__init__()
        self.main_entries = main_entries

    def add_menuitem(self, entry):
        """Add a menu item to the current menu

        Params:
            entry (tuple): tuple containing name, label and callback

        Returns:
            Gtk.MenuItem
        """
        name, label, callback = entry
        if label == "-":
            separator = Gtk.SeparatorMenuItem()
            self.append(separator)
            return separator

        action = Gtk.Action(name=name, label=label)
        action.connect("activate", callback)

        menu_item = action.create_menu_item()
        menu_item.action_id = name
        self.append(menu_item)
        return menu_item

    def popup(self, event, game_actions):
        for item in self.get_children():
            self.remove(item)

        for entry in self.main_entries:
            self.add_menuitem(entry)

        self.show_all()

        displayed = game_actions.get_displayed_entries()

        def is_visible(w):
            if isinstance(w, Gtk.SeparatorMenuItem):
                return None

            return displayed.get(w.action_id, True)

        visible_count = update_action_widget_visibility(self.get_children(), is_visible)

        if visible_count > 0:
            self.popup_at_pointer(event)
