import abc
from typing import Callable
import omni.ui as ui
from omni.kit.viewport.menubar.core import ViewportMenuDelegate


class SingleRenderMenuItemBase(ui.MenuItem):
    """
    A single menu item represent a single camera in the camera list
    """

    def __init__(
        self,
        display_name: str,
        engine_name,
        hd_engine_renderer,
        hd_renderer,
        viewport_api,
        enabled: bool,
        checked: bool,
        hide_on_click: bool,
        triggered_fn: Callable,
    ):
        self.__viewport_api = viewport_api
        self.__engine_name = engine_name
        self.__hd_engine_renderer = hd_engine_renderer
        self.__hd_renderer = hd_renderer
        self.__options_button = None

        super().__init__(
            display_name,
            enabled=enabled,
            checkable=True,
            checked=checked,
            delegate=ViewportMenuDelegate(
                force_checked=False,
                build_custom_widgets=lambda delegate, item: self._build_menuitem_widgets(),
            ),
            hide_on_click=hide_on_click,
            triggered_fn=triggered_fn
        )

    def destroy(self):
        self.__options_button = None
        super().destroy()

    @property
    def hd_renderer(self):
        return self.__hd_renderer

    @property
    def hd_engine_renderer(self):
        return self.__hd_engine_renderer

    @property
    def engine_name(self):
        return self.__engine_name

    @property
    def viewport_api(self):
        return self.__viewport_api

    def _build_menuitem_widgets(self):
        ui.Spacer(width=10)
        with ui.VStack(content_clipping=1, width=0):
            # Button to show renderer settings
            self.__options_button = ui.Button(
                style_type_name_override="Menu.Item.Button",
                name="OptionBox",
                width=16,
                height=16,
                image_width=16,
                image_height=16,
                visible=self.checked,
                clicked_fn=self._option_clicked,
            )

    @abc.abstractmethod
    def _option_clicked(self):
        """Function to implement when the option is clicked. Used by RTX Remix"""
        pass

    def set_checked(self, checked: bool) -> None:
        self.checked = checked
        self.delegate.checked = checked

        # Only show options button when it is current camera
        self.__options_button.visible = checked


class SingleRenderMenuItem(SingleRenderMenuItemBase):
    """
    A single menu item represent a single camera in the camera list
    """

    def _option_clicked(self):
        try:
            from omni.rtx.window.settings import RendererSettingsFactory
            rs_instance = RendererSettingsFactory.render_settings_extension_instance
            if rs_instance:
                rs_instance.show_render_settings(self.engine_name, self.hd_renderer.pluginID, True)
        except ImportError:
            pass
