# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto.  Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#

import omni.graph.core as og
import omni.kit.app
import omni.ui as ui

from . import UINodeCommon


class ComboBoxItem(ui.AbstractItem):
    def __init__(self, text):
        super().__init__()
        self.model = ui.SimpleStringModel(text)


class ComboBoxModel(ui.AbstractItemModel):
    def __init__(self, item_list):
        super().__init__()

        self._current_index = ui.SimpleIntModel(0)
        self._current_index.add_value_changed_fn(lambda index_model: self._item_changed(None))

        self._items = [ComboBoxItem(text) for text in item_list]

    def get_item_children(self, item=None):
        return self._items

    def get_item_value_model(self, item=None, column_id=0):
        if item is None:
            return self._current_index
        return item.model


class OgnComboBox:
    @staticmethod
    def internal_state():
        return UINodeCommon.OgnUINodeInternalState()

    @staticmethod
    def compute(db) -> bool:

        if db.inputs.create != og.ExecutionAttributeState.DISABLED:
            item_list = db.inputs.itemList
            if not item_list:
                db.log_error("The combo box must have at least one item!")
                return False

            width = db.inputs.width
            if width <= 0:
                db.log_error("The width of the combo box must be positive!")
                return False

            widget_identifier = UINodeCommon.get_unique_widget_identifier(db)

            parent_widget = UINodeCommon.get_parent_widget(db)
            if parent_widget is None:
                return False

            # Tear down previously created widget
            if db.internal_state.created_widget is not None:
                UINodeCommon.tear_down_widget(db)

            def on_combox_box_item_changed(model, item):
                if not db.internal_state.created_widget.enabled:
                    return
                current_index = model.get_item_value_model().as_int
                selected_child = model.get_item_children()[current_index]
                selected_value = model.get_item_value_model(selected_child).as_string

                message_bus = omni.kit.app.get_app().get_message_bus_event_stream()
                event_name = "value_changed_" + widget_identifier
                reg_event_name = UINodeCommon.registered_event_name(event_name)
                payload = {"newValue": selected_value, "valueType": "string"}
                message_bus.push(reg_event_name, payload=payload)

            # Now create the button widget and register callbacks
            with parent_widget:
                db.internal_state.created_frame = ui.Frame()
                with db.internal_state.created_frame:
                    with ui.HStack(content_clipping=1):
                        db.internal_state.created_widget = ui.ComboBox(
                            ComboBoxModel(item_list),
                            identifier=widget_identifier,
                            width=width,
                        )
                        db.internal_state.created_widget.model.add_item_changed_fn(on_combox_box_item_changed)

            db.outputs.created = og.ExecutionAttributeState.ENABLED
            db.outputs.widgetPath = UINodeCommon.find_widget_path(db.internal_state.created_widget)
            return True

        if db.inputs.tearDown != og.ExecutionAttributeState.DISABLED:
            return UINodeCommon.tear_down_widget(db)

        if db.inputs.show != og.ExecutionAttributeState.DISABLED:
            return UINodeCommon.show_widget(db)

        if db.inputs.hide != og.ExecutionAttributeState.DISABLED:
            return UINodeCommon.hide_widget(db)

        if db.inputs.enable != og.ExecutionAttributeState.DISABLED:
            return UINodeCommon.enable_widget(db)

        if db.inputs.disable != og.ExecutionAttributeState.DISABLED:
            return UINodeCommon.disable_widget(db)

        db.log_warning("Unexpected execution with no execution input enabled")
        return False
