# Copyright (c) 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.
#

import asyncio
import omni.ext
import carb
import carb.settings
import omni.kit.ui
from .viewport import get_viewport_interface
from .external_drag_drop_helper import setup_external_drag_drop, destroy_external_drag_drop


class Extension(omni.ext.IExt):
    def on_startup(self):
        # get window event stream
        viewport_win = get_viewport_interface().get_viewport_window()
        # on_mouse_event called when event dispatched
        if viewport_win:
            self._stage_event_sub = viewport_win.get_mouse_event_stream().create_subscription_to_pop(self.on_mouse_event)
        self._menu_path = "Window/New Viewport Window"
        self._editor_menu = omni.kit.ui.get_editor_menu()
        if self._editor_menu is not None:
            self._menu = self._editor_menu.add_item(self._menu_path, self._on_menu_click, False, priority=200)

        # external drag/drop
        if viewport_win:
            setup_external_drag_drop("Viewport")

    def on_shutdown(self):
        # remove event
        self._stage_event_sub = None
        destroy_external_drag_drop()

    def _on_menu_click(self, menu, toggled):
        async def new_viewport():
            await omni.kit.app.get_app().next_update_async()
            viewportFactory = get_viewport_interface()
            viewportHandle = viewportFactory.create_instance()
            window = viewportFactory.get_viewport_window(viewportHandle)
            window.set_window_size(350, 350)

        asyncio.ensure_future(new_viewport())

    def on_mouse_event(self, event):
        # check its expected event
        if event.type == int(omni.kit.ui.MenuEventType.ACTIVATE):
            if carb.settings.get_settings().get("/exts/omni.kit.window.viewport/showContextMenu"):
                self.show_context_menu(event.payload)

    def show_context_menu(self, payload: dict):
        viewport_win = get_viewport_interface().get_viewport_window()
        usd_context_name = viewport_win.get_usd_context_name()

        #This is actuall world-position !
        world_position = payload.get('mouse_pos_x', None)
        if world_position is not None:
            world_position = (
                world_position,
                payload['mouse_pos_y'],
                payload['mouse_pos_z']
            )

        try:
            from omni.kit.context_menu import ViewportMenu
            ViewportMenu.show_menu(
                usd_context_name, payload.get('prim_path', None), world_position
            )
        except ImportError:
            carb.log_error('omni.kit.context_menu must be loaded to use the context menu')

    @staticmethod
    def add_menu(menu_dict):
        """
        Add the menu to the end of the context menu. Return the object that
        should be alive all the time. Once the returned object is destroyed,
        the added menu is destroyed as well.
        """
        return omni.kit.context_menu.add_menu(menu_dict, "MENU", "omni.kit.window.viewport")

    @staticmethod
    def add_create_menu(menu_dict):
        """
        Add the menu to the end of the stage context create menu. Return the object that
        should be alive all the time. Once the returned object is destroyed,
        the added menu is destroyed as well.
        """
        return omni.kit.context_menu.add_menu(menu_dict, "CREATE", "omni.kit.window.viewport")
