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

__all__ = ['LegacyViewportWindow']


import omni.ui
import carb
import weakref


# Wrap a legacy viewport Window in an object that poses as a new omni.kit.viewport.window.ViewportWindow (omni.ui.Window) class

class LegacyViewportWindow(omni.ui.Window):
    def __init__(self, window_name: str, viewport_api = None, **kwargs):
        kwargs.update({
            'window_flags': omni.ui.WINDOW_FLAGS_NO_SCROLLBAR | omni.ui.WINDOW_FLAGS_NO_TITLE_BAR | omni.ui.WINDOW_FLAGS_NO_RESIZE
        })
        super().__init__(window_name, **kwargs)
        self.__z_stack = None
        with self.frame:
            self.__z_stack = omni.ui.ZStack()
        self.__window_name = window_name
        if not viewport_api:
            from .legacy_viewport_api import LegacyViewportAPI
            viewport_api = LegacyViewportAPI(window_name)
        self.__viewport_api = viewport_api
        self.__added_frames = {}

    @property
    def name(self):
        return self.__window_name

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

    def get_frame(self, name: str):
        frame = self.__added_frames.get(name)
        if frame is None:
            with self.__z_stack:
                frame = omni.ui.Frame(horizontal_clipping=True)
                self.__added_frames[name] = frame
        return frame

    @property
    def legacy_window(self):
        return self.__get_legacy_window()

    @property
    def width(self):
        return super().width

    @property
    def height(self):
        return super().height

    @width.setter
    def width(self, width: float):
        width = int(width)
        legacy_window = self.legacy_window
        if legacy_window:
            legacy_window.set_window_size(width, int(self.height))
        super(LegacyViewportWindow, self.__class__).width.fset(self, width)

    @height.setter
    def height(self, height: float):
        height = int(height)
        legacy_window = self.legacy_window
        if legacy_window:
            legacy_window.set_window_size(int(self.width), height)
        super(LegacyViewportWindow, self.__class__).height.fset(self, height)

    @property
    def position_x(self):
        pos_x = super().position_x
        # Workaround omni.ui reporting massive position_y unless laid out ?
        return pos_x if pos_x != 340282346638528859811704183484516925440 else 0

    @property
    def position_y(self):
        pos_y = super().position_y
        # Workaround omni.ui reporting massive position_y unless laid out ?
        return pos_y if pos_y != 340282346638528859811704183484516925440 else 0

    @position_x.setter
    def position_x(self, position_x: float):
        position_x = int(position_x)
        legacy_window = self.legacy_window
        if legacy_window:
            legacy_window.set_window_pos(position_x, int(self.position_y))
        super(LegacyViewportWindow, self.__class__).position_x.fset(self, position_x)

    @position_y.setter
    def position_y(self, position_y: float):
        position_y = int(position_y)
        legacy_window = self.legacy_window
        if legacy_window:
            legacy_window.set_window_pos(int(self.position_x), position_y)
        super(LegacyViewportWindow, self.__class__).position_y.fset(self, position_y)

    def setPosition(self, x: float, y: float):
        return self.set_position(x, y)

    def set_position(self, x: float, y: float):
        x, y = int(x), int(y)
        legacy_window = self.legacy_window
        if legacy_window:
            legacy_window.set_window_pos(x, y)
        super().setPosition(x, y)

    @property
    def visible(self):
        legacy_window = self.legacy_window
        if legacy_window:
            return legacy_window.is_visible()
        return super().visible

    @visible.setter
    def visible(self, visible: bool):
        visible = bool(visible)
        legacy_window = self.legacy_window
        if legacy_window:
            legacy_window.set_visible(visible)
        super(LegacyViewportWindow, self.__class__).visible.fset(self, visible)

    def __del__(self):
        self.destroy()

    def destroy(self):
        self.__viewport_api = None
        if self.__z_stack:
            self.__z_stack.clear()
            self.__z_stack.destroy()
            self.__z_stack = None
        if self.__added_frames:
            for name, frame in self.__added_frames.items():
                try:
                    frame.destroy()
                except Exception:
                    import traceback
                    carb.log_error(f"Error destroying {self.__window_name}. Traceback:\n{traceback.format_exc()}")
            self.__added_frames = None
        super().destroy()

    def _post_toast_message(self, message: str, message_id: str = None):
        legacy_window = self.legacy_window
        if legacy_window:
            return legacy_window.post_toast(message)

    def __get_legacy_window(self):
        import omni.kit.viewport_legacy as vp_legacy
        vp_iface = vp_legacy.get_viewport_interface()
        viewport_handle = vp_iface.get_instance(self.__window_name)
        return vp_iface.get_viewport_window(viewport_handle)
