import omni.ui as ui

from .option_item import OptionItem


class OptionMenuItemDelegate(ui.MenuDelegate):
    """
    Delegate for general option menu item.
    A general option item includes a selected icon and item text.

    Args:
        option_item (OptionItem): Option item to show as menu item.

    Keyword Args:
        width (ui.Length): Menu item width. Default ui.Fraction(1).
    """
    def __init__(self, option_item: OptionItem, width: ui.Length = ui.Fraction(1)):
        self._option_item = option_item
        self._width = width
        super().__init__(propagate=True)

    def destroy(self):
        self.__sub = None

    def build_item(self, item: ui.MenuItem):
        model = self._option_item.model
        self.__sub = model.subscribe_value_changed_fn(self._on_value_changed)
        self._container = ui.HStack(height=24, width=self._width, content_clipping=False, checked=model.as_bool)
        with self._container:
            ui.ImageWithProvider(width = 24, style_type_name_override="MenuItem.Icon")
            ui.Label(
                    item.text,
                    style_type_name_override="MenuItem.Label",
                )
            ui.Spacer(width=16)

        self._container.set_mouse_pressed_fn(lambda x, y, b, a, m=model: m.set_value(not m.as_bool))
        self._container.set_mouse_hovered_fn(self._on_mouse_hovered)

    def _on_value_changed(self, model: ui.SimpleBoolModel) -> None:
        self._container.checked = model.as_bool

    def _on_mouse_hovered(self, hovered: bool) -> None:
        # Here to set selected instead of hovered status for icon.
        # Because there is margin in icon, there will be some blank at top/bottom as a result icon does not become hovered if mouse on these area.
        self._container.selected = hovered


class OptionMenuItem(ui.MenuItem):
    """
    Represent a menu item for a single option.

    Args:
        option_item (OptionItem): Option item to show as menu item.
    
    Keyword Args:
        hide_on_click (bool): Hide menu if item clicked. Default False.
        width (ui.Length): Menu item width. Default ui.Fraction(1).
    """
    def __init__(self, option_item: OptionItem, hide_on_click: bool = False, width: ui.Length = ui.Fraction(1)):
        self._delegate = OptionMenuItemDelegate(option_item, width=width)
        super().__init__(option_item.text, delegate=self._delegate, hide_on_click=hide_on_click, checkable=True)

    def destroy(self):
        self._delegate.destroy()
