# 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 Styling"""

from .doc_page import DocPage
from functools import partial
from omni import ui
from omni.ui import color as cl
from omni.ui import constant as fl
from omni.ui import url
import inspect

SPACING = 5


def named_shades():
    def set_color(color):
        cl.example_color = color

    def set_width(value):
        fl.example_width = value

    cl.example_color = cl.green
    fl.example_width = 1.0

    with ui.HStack(height=100, spacing=5):
        with ui.ZStack():
            ui.Rectangle(
                style={
                    "background_color": cl.shade(
                        "aqua",
                        orange=cl.orange,
                        another=cl.example_color,
                        transparent=cl.transparent,
                        black=cl.black,
                    ),
                    "border_width": fl.shade(1, orange=4, another=8),
                    "border_radius": fl.one,
                    "border_color": cl.black,
                },
            )
            ui.Label(
                "ui.Rectangle(\n"
                "\tstyle={\n"
                '\t\t"background_color":\n'
                "\t\t\tcl.shade(\n"
                '\t\t\t\t"aqua",\n'
                "\t\t\t\torange=cl(1, 0.5, 0),\n"
                "\t\t\t\tanother=cl.example_color),\n"
                '\t\t"border_width":\n'
                "\t\t\tfl.shade(1, orange=4, another=8)})",
                alignment=ui.Alignment.CENTER,
                word_wrap=True,
                style={"color": cl.black, "margin": 15},
            )

        with ui.ZStack():
            ui.Rectangle(
                style={
                    "background_color": cl.example_color,
                    "border_width": fl.example_width,
                    "border_radius": fl.one,
                    "border_color": cl.black,
                }
            )
            ui.Label(
                "ui.Rectangle(\n"
                "\tstyle={\n"
                '\t\t"background_color": cl.example_color,\n'
                '\t\t"border_width": fl.example_width)})',
                alignment=ui.Alignment.CENTER,
                word_wrap=True,
                style={"color": cl.black, "margin": 15},
            )

    with ui.HStack():
        ui.Button("ui.set_shade()", clicked_fn=partial(ui.set_shade, ""))
        ui.Button('ui.set_shade("orange")', clicked_fn=partial(ui.set_shade, "orange"))
        ui.Button('ui.set_shade("another")', clicked_fn=partial(ui.set_shade, "another"))
    with ui.HStack():
        ui.Button("fl.example_width = 1", clicked_fn=partial(set_width, 1))
        ui.Button("fl.example_width = 4", clicked_fn=partial(set_width, 4))
    with ui.HStack():
        ui.Button('cl.example_color = "green"', clicked_fn=partial(set_color, "green"))
        ui.Button("cl.example_color = cl(0.8)", clicked_fn=partial(set_color, cl(0.8)))


def url_shades():
    def set_url(url_path: str):
        url.example_url = url_path

    walk = "resources/icons/Nav_Walkmode.png"
    fly = "resources/icons/Nav_Flymode.png"

    url.example_url = walk

    with ui.HStack(height=100, spacing=5):
        with ui.ZStack():
            ui.Image(style={"image_url": url.example_url})
            ui.Label(
                'ui.Image(\n\tstyle={"image_url": cl.example_url})\n',
                alignment=ui.Alignment.CENTER,
                word_wrap=True,
                style={"color": cl.black, "margin": 15},
            )
        with ui.ZStack():
            ui.ImageWithProvider(
                style={
                    "image_url": url.shade(
                        "resources/icons/Move_local_64.png",
                        another="resources/icons/Move_64.png",
                        orange="resources/icons/Rotate_local_64.png",
                    )
                }
            )
            ui.Label(
                "ui.ImageWithProvider(\n"
                "\tstyle={\n"
                '\t\t"image_url":\n'
                "\t\t\tst.shade(\n"
                '\t\t\t\t"Move_local_64.png",\n'
                '\t\t\t\tanother="Move_64.png")})\n',
                alignment=ui.Alignment.CENTER,
                word_wrap=True,
                style={"color": cl.black, "margin": 15},
            )

    with ui.HStack():
        ui.Button("ui.set_shade()", clicked_fn=partial(ui.set_shade, ""))
        ui.Button('ui.set_shade("another")', clicked_fn=partial(ui.set_shade, "another"))
    with ui.HStack():
        ui.Button("url.example_url = Nav_Walkmode.png", clicked_fn=partial(set_url, walk))
        ui.Button("url.example_url = Nav_Flymode.png", clicked_fn=partial(set_url, fly))


def font_size():
    def value_changed(label, value):
        label.style = {"color": ui.color(0), "font_size": value.as_float}

    slider = ui.FloatSlider(min=1.0, max=150.0)
    slider.model.as_float = 10.0
    label = ui.Label("Omniverse", style={"color": ui.color(0), "font_size": 7.0})
    slider.model.add_value_changed_fn(partial(value_changed, label))


class StylingDoc(DocPage):
    """ document for Styling workflow"""

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

        self._caption("The Style Sheet Syntax", navigate_to)

        self._text(
            "OMNI.UI Style Sheet rules are almost identical to those of HTML CSS. Style sheets consist of a sequence "
            "of style rules. A style rule is made up of a selector and a declaration. The selector specifies which "
            "widgets are affected by the rule; the declaration specifies which properties should be set on the widget. "
            "For example:"
        )

        with ui.VStack(width=0, style={"Button": {"background_color": cl("#097EFF")}}):
            ui.Button("Style Example")

        self._code(
            """
        with ui.VStack(width=0, style={"Button": {"background_color": cl("#097EFF")}}):
            ui.Button("Style Example")
            """
        )

        self._text(
            'In the above style rule, Button is the selector, and { "background_color": cl("#097EFF") } is the '
            "declaration. The rule specifies that Button should use blue as its background color."
        )

        with ui.VStack():
            self._table("Selector", "Example", "Explanation", cl.black)
            self._table("Type Selector", "Button", "Matches instances of Button.")
            self._table(
                "Name Selector", "Button::okButton", "Matches all Button instances whose object name is okButton."
            )
            self._table(
                "State Selector",
                "Button:hovered",
                "Matches all Button instances whose state is hovered. It means the mouse should be in the widget area. "
                "Pseudo-states appear at the end of the selector, with a colon (:) in between. The supported states are "
                "hovered and pressed.",
            )

        self._text("It's possible to omit the selector and override the property in all the widget types:")

        with ui.VStack(width=0, style={"background_color": cl("#097EFF")}):
            ui.Button("Style Example")

        self._code(
            """
        with ui.VStack(width=0, style={"background_color": cl("#097EFF")}):
            ui.Button("Style Example")
            """
        )

        self._text(
            "The difference with the previous button is that all the colors, including pressed color and hovered "
            "color, are overridden."
        )

        style1 = {
            "Button": {"border_width": 0.5, "border_radius": 0.0, "margin": 5.0, "padding": 5.0},
            "Button::one": {
                "background_color": cl("#097EFF"),
                "background_gradient_color": cl("#6DB2FA"),
                "border_color": cl("#1D76FD"),
            },
            "Button.Label::one": {"color": cl.white},
            "Button::one:hovered": {"background_color": cl("#006EFF"), "background_gradient_color": cl("#5AAEFF")},
            "Button::one:pressed": {"background_color": cl("#6DB2FA"), "background_gradient_color": cl("#097EFF")},
            "Button::two": {"background_color": cl.white, "border_color": cl("#B1B1B1")},
            "Button.Label::two": {"color": cl("#272727")},
            "Button::three:hovered": {
                "background_color": cl("#006EFF"),
                "background_gradient_color": cl("#5AAEFF"),
                "border_color": cl("#1D76FD"),
            },
            "Button::four:pressed": {
                "background_color": cl("#6DB2FA"),
                "background_gradient_color": cl("#097EFF"),
                "border_color": cl("#1D76FD"),
            },
        }

        with ui.HStack(style=style1):
            ui.Button("One", name="one")
            ui.Button("Two", name="two")
            ui.Button("Three", name="three")
            ui.Button("Four", name="four")
            ui.Button("Five", name="five")

        self._code(
            """
        style1 = {
            "Button": {
                "border_width": 0.5,
                "border_radius": 0.0,
                "margin": 5.0,
                "padding": 5.0
            },
            "Button::one": {
                "background_color": cl("#097EFF"),
                "background_gradient_color": cl("#6DB2FA"),
                "border_color": cl("#1D76FD"),
            },
            "Button.Label::one": {
                "color": cl.white,
            },
            "Button::one:hovered": {
                "background_color": cl("#006EFF"),
                "background_gradient_color": cl("#5AAEFF")
            },
            "Button::one:pressed": {
                "background_color": cl("#6DB2FA"),
                "background_gradient_color": cl("#097EFF")
            },
            "Button::two": {
                "background_color": cl.white,
                "border_color": cl("#B1B1B1")
            },
            "Button.Label::two": {
                "color": cl("#272727")
            },
            "Button::three:hovered": {
                "background_color": cl("#006EFF"),
                "background_gradient_color": cl("#5AAEFF"),
                "border_color": cl("#1D76FD"),
            },
            "Button::four:pressed": {
                "background_color": cl("#6DB2FA"),
                "background_gradient_color": cl("#097EFF"),
                "border_color": cl("#1D76FD"),
            },
        }

        with ui.HStack(style=style1):
            ui.Button("One", name="one")
            ui.Button("Two", name="two")
            ui.Button("Three", name="three")
            ui.Button("Four", name="four")
            ui.Button("Five", name="five")
            """
        )

        self._text(
            "It's possible to assign any style override to any level of the widget. It can be assigned to both parents "
            "and children at the same time."
        )

        with ui.HStack(style=self._style_system):
            ui.Button("One")
            ui.Button("Two", style={"color": cl("#AAAAAA")})
            ui.Button("Three", style={"background_color": cl("#097EFF"), "background_gradient_color": cl("#6DB2FA")})
            ui.Button(
                "Four", style={":hovered": {"background_color": cl("#006EFF"), "background_gradient_color": cl("#5AAEFF")}}
            )
            ui.Button(
                "Five",
                style={"Button:pressed": {"background_color": cl("#6DB2FA"), "background_gradient_color": cl("#097EFF")}},
            )

        self._code(
            """
        style_system = {
            "Button": {
                "background_color": cl("#E1E1E1"),
                "border_color": cl("#ADADAD"),
                "border_width": 0.5,
                "border_radius": 0.0,
                "margin": 5.0,
                "padding": 5.0,
            },
            "Button.Label": {
                "color": cl.black,
            },
            "Button:hovered": {
                "background_color": cl("#E5F1FB"),
                "border_color": cl("#0078D7")
            },
            "Button:pressed": {
                "background_color": cl("#CCE4F7"),
                "border_color": cl("#005499"),
                "border_width": 1.0
            },
        }

        with ui.HStack(style=style_system):
            ui.Button("One")
            ui.Button("Two", style={"color": cl("#AAAAAA")})
            ui.Button("Three", style={
                "background_color": cl("#097EFF"),
                "background_gradient_color": cl("#6DB2FA")}
            )
            ui.Button(
                "Four", style={
                    ":hovered": {
                        "background_color": cl("#006EFF"),
                        "background_gradient_color": cl("#5AAEFF")
                    }
                }
            )
            ui.Button(
                "Five",
                style={
                    "Button:pressed": {
                        "background_color": cl("#6DB2FA"),
                        "background_gradient_color": cl("#097EFF")
                    }
                },
            )
            """
        )

        self._caption("Color Syntax", navigate_to)

        self._text(
            "There are many ways that colors can be described with omni.ui.color.  If alpha is not specified, it is assumed to be 255 or 1.0."
        )

        self._code(
            """
        from omni.ui import color as cl
        cl("#CCCCCC")      # RGB
        cl("#CCCCCCFF")    # RGBA
        cl(128, 128, 128)  # RGB
        cl(0.5, 0.5, 0.5)  # RGB
        cl(128, 128, 128, 255)  # RGBA
        cl(0.5, 0.5, 0.5, 1.0)  # RGBA
        cl(128)  # RGB all the same
        cl(0.5)  # RGB all the same
        cl.blue
            """
        )

        self._text(
            "Note: You may see something like this syntax in older code, but that syntax is not suggested anymore:"
        )

        self._code('"background_color": 0xFF886644  # Same as cl("#446688FF")')

        self._text(
            "Because of the way bytes are packed with little-endian format in that syntax, the color components appear to be backwards (ABGR). "
            "Going forward only omni.ui.color syntax should be used."
        )

        self._caption("Shades", navigate_to)

        self._text(
            "Shades are used to have multiple named color palettes with the ability to runtime switch. The shade can "
            "be defined with the following code:"
        )

        self._code('cl.shade(cl("#0066FF"), red=cl.red, green=cl("#00FF66"))')

        self._text(
            "It can be assigned to the color style. It's possible to switch the color with the following command "
            "globally:"
        )

        self._code('cl.set_shade("red")')

        named_shades()
        self._code(inspect.getsource(named_shades).split("\n", 1)[-1])

        self._caption("URL Shades", navigate_to)

        self._text("It's also possible to use shades for specifying shortcuts to the images and style-based paths.")
        url_shades()
        self._code(inspect.getsource(url_shades).split("\n", 1)[-1])

        self._caption("Font Size", navigate_to)

        self._text("It's possible to set the font size with the style:")

        font_size()
        self._code(inspect.getsource(font_size).split("\n", 1)[-1])

        ui.Spacer(height=10)
