# 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 of the omni.ui aka UI Framework"""
# Add imports here that are needed in the _exec_code calls.
from omni import ui
from omni.ui import color as cl
import omni.usd
from pxr import Usd
from pxr import UsdGeom
import subprocess
import sys

SPACING = 5


class DocPage:
    """The Demo extension"""

    def __init__(self, extension_path):
        self._extension_path = extension_path
        self._style_system = {
            "Button": {
                "background_color": 0xFFE1E1E1,
                "border_color": 0xFFADADAD,
                "border_width": 0.5,
                "border_radius": 0.0,
                "margin": 5.0,
                "padding": 5.0,
            },
            "Button.Label": {"color": 0xFF000000},
            "Button:hovered": {"background_color": 0xFFFBF1E5, "border_color": 0xFFD77800},
            "Button:pressed": {"background_color": 0xFFF7E4CC, "border_color": 0xFF995400, "border_width": 1.0},
        }
        self._copy_context_menu = ui.Menu("Copy Context menu", name="this")

    def clean(self):
        """Should be called when the extesion us unloaded or reloaded"""
        pass

    def _show_copy_menu(self, x, y, button, modifier, text):
        """The context menu to copy the text"""
        # Display context menu only if the right button is pressed
        if button != 1:
            return

        def copy_text(text_value):
            # we need to find a cross plartform way currently Window Only
            subprocess.run(["clip.exe"], input=text_value.strip().encode("utf-8"), check=True)

        # Reset the previous context popup
        self._copy_context_menu.clear()
        with self._copy_context_menu:
            ui.MenuItem("Copy Code", triggered_fn=lambda t=text: copy_text(t))

        # Show it
        self._copy_context_menu.show()

    def create_doc(self, navigate_to=None):
        """
        Class should overide this methods.

        Args:
            navigate_to: The chapter it's necessary to navigate the scrollbar.
        """
        pass

    def _text(self, text):
        """Create a formated paragraph of the text"""
        ui.Label(text, name="text", word_wrap=True, skip_draw_when_clipped=True)

    def _section_title(self, text):
        """Create a title separator"""
        with ui.ZStack():
            ui.Rectangle(name="section")
            ui.Label(text, name="section", alignment=ui.Alignment.CENTER)

    def _caption(self, text, navigate_to=None):
        """Create a formated heading"""
        with ui.ZStack():
            background = ui.Rectangle(name="caption")
            if navigate_to == text:
                background.scroll_here_y(0.0)

            ui.Label(text, name="caption", alignment=ui.Alignment.LEFT_CENTER)

    def _code(self, text, elided_text=False):
        """Create a code snippet"""
        stack = ui.ZStack()
        with stack:
            ui.Rectangle(name="code")
            label = ui.Label(text, name="code", skip_draw_when_clipped=True, elided_text=elided_text)

        if not sys.platform == "linux":
            stack.set_mouse_pressed_fn(lambda x, y, b, m, text=text: self._show_copy_menu(x, y, b, m, text))

        return label

    def _exec_code(self, code):
        """Execute the code and create a snippet"""
        # Python magic to capture output of exec
        locals_from_execution = {}
        exec(f"class Execution():\n  def __init__(self):\n{code}", None, locals_from_execution)
        self._first = locals_from_execution["Execution"]()

        self._code(code)

    def _image_table(self, code, description, description_width=ui.Fraction(1), code_width=ui.Fraction(1)):
        """Create a row of the table that demostrates images"""
        # TODO: We need to use style padding instead of thousands of spacers
        with ui.HStack():
            with ui.ZStack(width=140):
                ui.Rectangle(name="table")
                with ui.HStack():
                    ui.Spacer(width=SPACING / 2)
                    with ui.VStack():
                        ui.Spacer(height=SPACING / 2)
                        # Execute the provided code
                        exec(code)
                        ui.Spacer(height=SPACING / 2)
                    ui.Spacer(width=SPACING / 2)
            with ui.ZStack(width=description_width):
                ui.Rectangle(name="table")
                with ui.HStack():
                    ui.Spacer(width=SPACING / 2)
                    ui.Label(description, style={"margin": 5}, name="text", word_wrap=True)
                    ui.Spacer(width=SPACING / 2)
            with ui.ZStack(width=code_width):
                ui.Rectangle(name="table")
                with ui.HStack():
                    ui.Spacer(width=SPACING / 2)
                    with ui.VStack():
                        ui.Spacer(height=SPACING / 2)
                        with ui.ZStack():
                            ui.Rectangle(name="code")
                            ui.Label(f"\n\t{code}\n\n", name="code")
                        ui.Spacer(height=SPACING / 2)
                    ui.Spacer(width=SPACING / 2)

    def _shape_table(self, code, description, row_height=0):
        """Create a row of the table that demostrates images"""
        # TODO: We need to use style padding instead of thousands of spacers
        with ui.HStack(height=row_height):
            with ui.ZStack():
                ui.Rectangle(name="table")
                # Execute the provided code
                with ui.ZStack(name="margin", style={"ZStack::margin": {"margin": SPACING * 2}}):
                    ui.Rectangle(name="code")
                    exec(code)
            with ui.ZStack(width=ui.Fraction(2)):
                ui.Rectangle(name="table")
                ui.Label(description, name="text", style={"margin": SPACING}, word_wrap=True)
            with ui.ZStack(width=300):
                ui.Rectangle(name="table")
                with ui.ZStack(name="margin", style={"ZStack::margin": {"margin": SPACING / 2}}):
                    ui.Rectangle(name="code")
                    ui.Label(f"\n\t{code}\n\n", name="code")

    def _table(self, selector, example, explanatoin, color=None):
        """Create a one row of a table"""
        localStyle = {}
        if color is not None:
            localStyle = {"color": color}
        # TODO: We need to use style padding instead of thousands of spacers
        with ui.HStack(height=0, style=localStyle):
            with ui.ZStack(width=100):
                ui.Rectangle(name="table")
                with ui.HStack(height=0):
                    ui.Spacer(width=SPACING)
                    ui.Label(selector, name="text")
                    ui.Spacer(width=SPACING)
            with ui.ZStack(width=120):
                ui.Rectangle(name="table")
                with ui.HStack(height=0):
                    ui.Spacer(width=SPACING)
                    ui.Label(example, name="text")
                    ui.Spacer(width=SPACING)
            with ui.ZStack():
                ui.Rectangle(name="table")
                with ui.HStack(height=0):
                    ui.Spacer(width=SPACING)
                    ui.Label(explanatoin, name="text", word_wrap=True)
                    ui.Spacer(width=SPACING)
