# Copyright (c) 2018-2020, 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.
#
"""The documentation for ComboBox"""

from omni import ui
from .doc_page import DocPage


class ComboBoxDoc(DocPage):
    """ document for ComboBox"""

    def create_doc(self, navigate_to=None):
        self._section_title("ComboBox")

        self._text("The ComboBox widget is a combined button and a drop-down list.")

        self._text(
            "A combo box is a selection widget that displays the current item and can pop up a list of selectable "
            "items."
        )

        self._exec_code(
            """
        ui.ComboBox(1, "Option 1", "Option 2", "Option 3")
            """
        )

        self._text("The following example demonstrates how to add items to the combo box.")

        self._exec_code(
            """
        editable_combo = ui.ComboBox()
        ui.Button(
            "Add item to combo",
            clicked_fn=lambda m=editable_combo.model: m.append_child_item(
                None, ui.SimpleStringModel("Hello World")),
        )
            """
        )

        self._text("The minimal model implementation. It requires to hold the value models and reimplement two methods.")

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

        class MinimalModel(ui.AbstractItemModel):
            def __init__(self):
                super().__init__()

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

                self._items = [
                    MinimalItem(text)
                    for text in ["Option 1", "Option 2"]
                ]

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

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

        self._minimal_model = MinimalModel()
        ui.ComboBox(self._minimal_model, style={"font_size": 22})
            """
        )

        self._text(
            "The example of communication between widgets. Type anything in the field and it will appear in the combo "
            "box."
        )

        self._exec_code(
            """
        editable_combo = None

        class StringModel(ui.SimpleStringModel):
            '''
            String Model activated when editing is finished.
            Adds item to combo box.
            '''
            def __init__(self):
                super().__init__("")

            def end_edit(self):
                combo_model = editable_combo.model
                # Get all the options ad list of strings
                all_options = [
                    combo_model.get_item_value_model(child).as_string
                    for child in combo_model.get_item_children()
                ]

                # Get the current string of this model
                fieldString = self.as_string
                if fieldString:
                    if fieldString in all_options:
                        index = all_options.index(fieldString)
                    else:
                        # It's a new string in the combo box
                        combo_model.append_child_item(
                            None,
                            ui.SimpleStringModel(fieldString)
                        )
                        index = len(all_options)

                    combo_model.get_item_value_model().set_value(index)

        self._field_model = StringModel()

        def combo_changed(combo_model, item):
            all_options = [
                combo_model.get_item_value_model(child).as_string
                for child in combo_model.get_item_children()
            ]
            current_index = combo_model.get_item_value_model().as_int
            self._field_model.as_string = all_options[current_index]

        with ui.HStack():
            ui.StringField(self._field_model)
            editable_combo = ui.ComboBox(width=0, arrow_only=True)
            editable_combo.model.add_item_changed_fn(combo_changed)
            """
        )

        ui.Spacer(height=10)

        # TODO omni.ui: restore functionality for Kit Next
        if True:
            return

        self._text("The USD example. It tracks the stage cameras and can assign the current camera.")

        self._exec_code(
            """
        class CamerasItem(ui.AbstractItem):
            def __init__(self, model):
                super().__init__()
                self.model = model

        class CamerasModel(ui.AbstractItemModel):
            def __init__(self):
                super().__init__()

                # Omniverse interfaces
                self._viewport = omni.kit.viewport.utility.get_active_viewport()
                self._stage_update = \\
                    omni.stageupdate.get_stage_update_interface()
                self._usd_context = omni.usd.get_context()
                self._stage_subscription = \\
                    self._stage_update.create_stage_update_node(
                        "CamerasModel",
                        None,
                        None,
                        None,
                        self._on_prim_created,
                        None,
                        self._on_prim_removed
                    )

                # The list of the cameras is here
                self._cameras = []

                # The current index of the editable_combo box
                self._current_index = ui.SimpleIntModel()
                self._current_index.add_value_changed_fn(
                    self._current_index_changed)

                # Iterate the stage and get all the cameras
                stage = self._usd_context.get_stage()
                for prim in Usd.PrimRange(stage.GetPseudoRoot()):
                    if prim.IsA(UsdGeom.Camera):
                        self._cameras.append(
                            CamerasItem(
                                ui.SimpleStringModel(
                                    prim.GetPath().pathString)))

            def get_item_children(self, item):
                return self._cameras

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

                return item.model

            def _on_prim_created(self, path):
                self._cameras.append(
                    CamerasItem(ui.SimpleStringModel(path)))
                self._item_changed(None)

            def _on_prim_removed(self, path):
                cameras = [cam.model.as_string for cam in self._cameras]
                if path in cameras:
                    index = cameras.index(path)
                    del self._cameras[index]
                    self._current_index.as_int = 0
                    self._item_changed(None)

            def _current_index_changed(self, model):
                index = model.as_int
                self.self._viewport.camera_path = self._cameras[index].model.as_string
                self._item_changed(None)

        self._combo_model = CamerasModel()
        ui.ComboBox(self._combo_model)
            """
        )
