
__all__ = ["InspectorPreview"]

from typing import Union
import omni.ui as ui
import omni.kit.app
import carb.events
import carb

from omni.ui_query import OmniUIQuery
from omni.kit.widget.inspector import InspectorWidget, PreviewMode

class InspectorPreview:
    """The Stage widget"""

    def destroy(self):
        self._window = None
        self._inspector = None

    def __init__(self, window: ui.Window, **kwargs):
        self._window = window
        self._widget = window.frame if window else None
        self._preview_mode = ["BOTH", "WIRE", "COLOR"]
        self._preview_mode_model = None
        self._inspector: Union[ui.Inspector, None] = None
        self._main_stack = ui.VStack()

        self._sender_id = hash("InspectorPreview") & 0xFFFFFFFF

        self._build_ui()

        app = omni.kit.app.get_app()
        self._update_sub = app.get_message_bus_event_stream().create_subscription_to_pop(
            self.on_selection_changed, name="Inspector Selection Changed"
        )

    def on_selection_changed(self, event: carb.events.IEvent):
        if event.sender == self._sender_id:
            # we don't respond to our own events
            return

        from .inspector_widget import INSPECTOR_ITEM_SELECTED_ID, INSPECTOR_PREVIEW_CHANGED_ID

        if event.type == INSPECTOR_ITEM_SELECTED_ID:
            selection = OmniUIQuery.find_widget(event.payload["item_path"])
            if selection:
                self.set_widget(selection)
        elif event.type == INSPECTOR_PREVIEW_CHANGED_ID:
            selection = OmniUIQuery.find_widget(event.payload["item_path"])
            if selection:
                if "window_name" in event.payload:
                    window_name = event.payload["window_name"]
                    window = ui.Workspace.get_window(window_name)
                    if window:
                        self._window = window
                    else:
                        carb.log_error(f"Failed to find {window_name}")

                self.set_main_widget(selection)

    def toggle_visibility(self):
        self._main_stack.visible = not self._main_stack.visible

    def _build_ui(self):
        with self._main_stack:
            ui.Spacer(height=5)
            with ui.ZStack():
                ui.Rectangle(name="render_background", style={"background_color": 0xFF333333})
                with ui.VStack():
                    ui.Spacer(height=10)
                    with ui.ZStack():
                        ui.Rectangle()
                        with ui.HStack():
                            self._inspector = InspectorWidget(widget=self._widget)

                            def selection_changed(widget):
                                # Send the Selection Changed Message
                                from .inspector_widget import INSPECTOR_ITEM_SELECTED_ID

                                stream = omni.kit.app.get_app().get_message_bus_event_stream()
                                widget_path = OmniUIQuery.get_widget_path(self._window, widget)
                                if widget_path:
                                    stream.push(
                                        INSPECTOR_ITEM_SELECTED_ID,
                                        sender=self._sender_id,
                                        payload={"item_path": widget_path},
                                    )

                            self._inspector.set_selected_widget_changed_fn(selection_changed)

            with ui.HStack(height=0):
                ui.Label("Depth", width=0)
                ui.Spacer(width=4)

                def value_changed_fn(model: ui.AbstractValueModel):
                    self._inspector.depth_scale = float(model.as_int)

                model = ui.IntDrag(min=0, max=300, width=40).model
                model.set_value(50)
                model.add_value_changed_fn(value_changed_fn)

                ui.Spacer()

                # def build Preview Type Radio
                with ui.HStack(width=0, style={"margin": 0, "padding_width": 6, "border_radius": 0}):
                    self._preview_mode_collection = ui.RadioCollection()

                    def preview_mode_changed(item: ui.AbstractValueModel):
                        index = item.as_int
                        if index == 0:
                            self._inspector.preview_mode = PreviewMode.WIREFRAME_AND_COLOR
                        elif index == 1:
                            self._inspector.preview_mode = PreviewMode.WIRE_ONLY
                        else:
                            self._inspector.preview_mode = PreviewMode.COLOR_ONLY

                    self._preview_mode_collection.model.add_value_changed_fn(preview_mode_changed)

                    for preview_mode in self._preview_mode:
                        style = {}
                        radius = 4
                        if preview_mode == "BOTH":
                            style = {"border_radius": radius, "corner_flag": ui.CornerFlag.LEFT}
                        if preview_mode == "COLOR":
                            style = {"border_radius": radius, "corner_flag": ui.CornerFlag.RIGHT}

                        ui.RadioButton(
                            width=50, style=style, text=preview_mode, radio_collection=self._preview_mode_collection
                        )

                    def preview_mode_value_changed(value):
                        if value == PreviewMode.WIREFRAME_AND_COLOR:
                            self._preview_mode_collection.model.set_value(0)
                        elif value == PreviewMode.WIRE_ONLY:
                            self._preview_mode_collection.model.set_value(1)
                        elif value == PreviewMode.COLOR_ONLY:
                            self._preview_mode_collection.model.set_value(2)

                    self._inspector.set_preview_mode_change_fn(preview_mode_value_changed)

                ui.Spacer()
                ui.Label("Range  ", width=0)

                def min_value_changed_fn(model: ui.AbstractValueModel):
                    self._inspector.start_depth = model.as_int

                model = ui.IntDrag(min=0, max=20, width=50).model.add_value_changed_fn(min_value_changed_fn)

                ui.Spacer(width=4)

                def max_value_changed_fn(model: ui.AbstractValueModel):
                    self._inspector.end_depth = model.as_int

                ui.IntDrag(min=0, max=6000, width=50).model.add_value_changed_fn(max_value_changed_fn)

    def set_main_widget(self, widget: ui.Widget):
        self._widget = widget
        self._inspector.widget = widget

    def set_widget(self, widget: ui.Widget):
        self._inspector.selected_widget = widget

    def update_window(self, window: ui.Window):
        self._inspector = None
        self._window = window
        self._widget = window.frame
        self._main_stack.clear()
        self._build_ui()
