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

from omni import ui
from omni.ui import color as cl
from .doc_page import DocPage
import inspect

SPACING = 5


def editable_curve():
    with ui.ZStack(height=400):
        # The Bezier tangents
        tangents = [(50, 50), (-50, -50)]

        # Four draggable rectangles that represent the control points
        placer1 = ui.Placer(draggable=True, offset_x=0, offset_y=0)
        with placer1:
            rect1 = ui.Rectangle(width=20, height=20)
        placer2 = ui.Placer(draggable=True, offset_x=50, offset_y=50)
        with placer2:
            rect2 = ui.Rectangle(width=20, height=20)
        placer3 = ui.Placer(draggable=True, offset_x=100, offset_y=100)
        with placer3:
            rect3 = ui.Rectangle(width=20, height=20)
        placer4 = ui.Placer(draggable=True, offset_x=150, offset_y=150)
        with placer4:
            rect4 = ui.Rectangle(width=20, height=20)

        # The bezier curve
        curve = ui.FreeBezierCurve(rect1, rect4)
        curve.start_tangent_width = ui.Pixel(tangents[0][0])
        curve.start_tangent_height = ui.Pixel(tangents[0][1])
        curve.end_tangent_width = ui.Pixel(tangents[1][0])
        curve.end_tangent_height = ui.Pixel(tangents[1][1])

        # The logic of moving the control points
        def left_moved(_):
            x = placer1.offset_x
            y = placer1.offset_y
            tangent = tangents[0]
            placer2.offset_x = x + tangent[0]
            placer2.offset_y = y + tangent[1]

        def right_moved(_):
            x = placer4.offset_x
            y = placer4.offset_y
            tangent = tangents[1]
            placer3.offset_x = x + tangent[0]
            placer3.offset_y = y + tangent[1]

        def left_tangent_moved(_):
            x1 = placer1.offset_x
            y1 = placer1.offset_y
            x2 = placer2.offset_x
            y2 = placer2.offset_y
            tangent = (x2 - x1, y2 - y1)
            tangents[0] = tangent
            curve.start_tangent_width = ui.Pixel(tangent[0])
            curve.start_tangent_height = ui.Pixel(tangent[1])

        def right_tangent_moved(_):
            x1 = placer4.offset_x
            y1 = placer4.offset_y
            x2 = placer3.offset_x
            y2 = placer3.offset_y
            tangent = (x2 - x1, y2 - y1)
            tangents[1] = tangent
            curve.end_tangent_width = ui.Pixel(tangent[0])
            curve.end_tangent_height = ui.Pixel(tangent[1])

        # Callback for moving the control points
        placer1.set_offset_x_changed_fn(left_moved)
        placer1.set_offset_y_changed_fn(left_moved)
        placer2.set_offset_x_changed_fn(left_tangent_moved)
        placer2.set_offset_y_changed_fn(left_tangent_moved)
        placer3.set_offset_x_changed_fn(right_tangent_moved)
        placer3.set_offset_y_changed_fn(right_tangent_moved)
        placer4.set_offset_x_changed_fn(right_moved)
        placer4.set_offset_y_changed_fn(right_moved)


def editable_rect():
    with ui.ZStack(height=200):
        # Four draggable rectangles that represent the control points
        with ui.Placer(draggable=True, offset_x=0, offset_y=0):
            control1 = ui.Circle(width=10, height=10, name="default")
        with ui.Placer(draggable=True, offset_x=150, offset_y=150):
            control2 = ui.Circle(width=10, height=10, name="default")

        # The rectangle that fits to the control points
        ui.FreeRectangle(control1, control2)


class ShapeDoc(DocPage):
    """ document for Shapes"""

    def create_doc(self, navigate_to=None):
        """ descriptions for the shapes widgets"""

        self._section_title("Shape")
        self._text("Shape enable you to build custom widget with specific look")
        self._text("There are many shape you can use, Rectangle, Circle, Triangle, Line, etc")
        self._text(
            "In most case those Shape will fit into the Widget size and scale accoringly to the layout they are in "
            "For some of them you can fix the size to enable to have more precise control over they size"
        )

        self._caption("Rectangle", navigate_to)
        self._text(
            "You can use Rectable to draw rectangle shape, you can have backgroundColor, borderColor, "
            "borderWidth, border_radius. mixed it with other controls using ZStack to create advance look"
        )

        with ui.VStack():
            self._shape_table(f"""ui.Rectangle(name="default")""", "(Default) The rectangle is scaled to fit")

            self._shape_table(
                """ui.Rectangle(
                        style={"background_color": cl("#888888"),
                                "border_color": cl("#222222"),
                                "border_width": 2.0,
                                "border_radius": 5.0} )""",
                "this rectangle use its own style to control colors and shape",
            )

            self._shape_table(
                """ui.Rectangle( width=20, height=20,
                        style={"background_color": cl("#888888"),
                                "border_color": cl("#222222")} )""",
                "using fixed width and height",
            )

            self._shape_table(
                """with ui.ZStack(height=20):
                    ui.Rectangle(height=20,
                        style={"background_color": cl("#888888"),
                                "border_color": cl("#111111"),
                                "border_width": .5,
                                "border_radius": 8.0} )
                    with ui.HStack():
                        ui.Spacer(width=10)
                        ui.Image(
                            "resources/icons/Cloud.png",
                            width=20,
                            height=20
                        )
                        ui.Label(
                            "Search Field",
                            style={"color": cl("#DDDDDD")}
                        )""",
                "Compose with ZStack for advanced control",
            )

        self._text("Support for specific Rounded Corner")

        corner_flags = {
            "NONE": ui.CornerFlag.NONE,
            "TOP_LEFT": ui.CornerFlag.TOP_LEFT,
            "TOP_RIGHT": ui.CornerFlag.TOP_RIGHT,
            "BOTTOM_LEFT": ui.CornerFlag.BOTTOM_LEFT,
            "BOTTOM_RIGHT": ui.CornerFlag.BOTTOM_RIGHT,
            "TOP": ui.CornerFlag.TOP,
            "BOTTOM": ui.CornerFlag.BOTTOM,
            "LEFT": ui.CornerFlag.LEFT,
            "RIGHT": ui.CornerFlag.RIGHT,
            "ALL": ui.CornerFlag.ALL,
        }

        with ui.ScrollingFrame(
            height=100,
            vertical_scrollbar_policy=ui.ScrollBarPolicy.SCROLLBAR_ALWAYS_OFF,
            style={"ScrollingFrame": {"background_color": cl.transparent}},
        ):
            with ui.HStack():
                for key, value in corner_flags.items():
                    with ui.ZStack():
                        ui.Rectangle(name="table")
                        with ui.VStack(style={"VStack": {"margin": SPACING * 2}}):
                            ui.Rectangle(
                                style={"background_color": cl("#AA4444"), "border_radius": 20.0, "corner_flag": value}
                            )
                            ui.Spacer(height=10)
                            ui.Label(key, style={"color": cl.black, "font_size": 8}, alignment=ui.Alignment.CENTER)

        self._caption("Circle", navigate_to)
        self._text("You can use Circle to draw circular shape, you can have backgroundColor, borderColor, borderWidth")

        with ui.VStack():
            self._shape_table(
                f"""ui.Circle(name="default")""", "(Default) The circle is scaled to fit, the alignment is centered"
            )

            self._shape_table(
                f"""ui.Circle(name="default")""", "This circle, is scaled to Fit too with the Row 100 height", 100
            )

            self._shape_table(
                f"""ui.Circle(
                    name="blue",
                    radius=20,
                    size_policy=ui.CircleSizePolicy.FIXED,
                    alignment=ui.Alignment.LEFT_CENTER)""",
                "This circle has a fixed radius of 20, the alignment is LEFT_CENTER",
            )

            self._shape_table(
                f"""ui.Circle(
                    name="red",
                    radius=10,
                    size_policy=ui.CircleSizePolicy.FIXED,
                    alignment=ui.Alignment.RIGHT_CENTER)""",
                "This circle has a fixed radius of 10, the alignment is RIGHT_CENTER",
            )

            self._shape_table(
                """ui.Circle(
                    style={"background_color": cl("#00FFFF"),},
                    size_policy=ui.CircleSizePolicy.STRETCH,
                    alignment=ui.Alignment.CENTER_TOP)""",
                "This circle has a radius to fill the bound, with an alignment is CENTER_TOP",
            )

            self._shape_table(
                """ui.Circle(
                    style={"background_color": cl.green,
                        "border_color": cl.blue,
                        "border_width": 5},
                    radius=10,
                    size_policy=ui.CircleSizePolicy.FIXED,
                    alignment=ui.Alignment.CENTER_BOTTOM)""",
                "This circle has a fixed radius of 5, the alignment is CENTER_BOTTOM, and a custom style ",
            )

        self._text("Supported Alignment value for the Circle")
        alignments = {
            "CENTER": ui.Alignment.CENTER,
            "LEFT_TOP": ui.Alignment.LEFT_TOP,
            "LEFT_CENTER": ui.Alignment.LEFT_CENTER,
            "LEFT_BOTTOM": ui.Alignment.LEFT_BOTTOM,
            "CENTER_TOP": ui.Alignment.CENTER_TOP,
            "CENTER_BOTTOM": ui.Alignment.CENTER_BOTTOM,
            "RIGHT_TOP": ui.Alignment.RIGHT_TOP,
            "RIGHT_CENTER": ui.Alignment.RIGHT_CENTER,
            "RIGHT_BOTTOM": ui.Alignment.RIGHT_BOTTOM,
        }
        with ui.ScrollingFrame(
            height=150,
            vertical_scrollbar_policy=ui.ScrollBarPolicy.SCROLLBAR_ALWAYS_OFF,
            style={"ScrollingFrame": {"background_color": cl.transparent}},
        ):
            with ui.HStack():
                for key, value in alignments.items():
                    with ui.ZStack():
                        ui.Rectangle(name="table")
                        with ui.VStack(style={"VStack": {"margin": SPACING * 2}}, spacing=SPACING * 2):
                            with ui.ZStack():
                                ui.Rectangle(name="table")
                                ui.Circle(
                                    radius=10,
                                    size_policy=ui.CircleSizePolicy.FIXED,
                                    name="orientation",
                                    alignment=value,
                                    style={"background_color": cl("#AA4444")},
                                )
                            ui.Label(key, style={"color": cl.black, "font_size": 8}, alignment=ui.Alignment.CENTER)

        self._caption("Triangle", navigate_to)
        self._text(
            "You can use Triangle to draw Triangle shape, you can have backgroundColor, borderColor, borderWidth"
        )

        with ui.VStack():
            self._shape_table(
                f"""ui.Triangle(name="default")""",
                "(Default) The triange is scaled to fit, base on the left and tip on the center right",
                100,
            )

            self._shape_table(
                """ui.Triangle(
                    style={"border_color": cl.black,
                        "border_width": 2},
                    alignment=ui.Alignment.CENTER_TOP)""",
                "Default triange with custom color and border",
                100,
            )

        self._text("the Alignment define where is the Tip of the Triangle, base will be at the oposite side")
        alignments = {
            "LEFT_TOP": ui.Alignment.LEFT_TOP,
            "LEFT_CENTER": ui.Alignment.LEFT_CENTER,
            "LEFT_BOTTOM": ui.Alignment.LEFT_BOTTOM,
            "CENTER_TOP": ui.Alignment.CENTER_TOP,
            "CENTER_BOTTOM": ui.Alignment.CENTER_BOTTOM,
            "RIGHT_TOP": ui.Alignment.RIGHT_TOP,
            "RIGHT_CENTER": ui.Alignment.RIGHT_CENTER,
            "RIGHT_BOTTOM": ui.Alignment.RIGHT_BOTTOM,
        }
        colors = [cl.red, cl("#FFFF00"), cl("#FF00FF"), cl("#FF0FF0"), cl.green, cl("#F00FFF"), cl("#FFF000"), cl("#AA3333")]
        index = 0
        with ui.ScrollingFrame(
            height=100,
            vertical_scrollbar_policy=ui.ScrollBarPolicy.SCROLLBAR_ALWAYS_OFF,
            style={"ScrollingFrame": {"background_color": cl.transparent}},
        ):
            with ui.HStack():
                for key, value in alignments.items():
                    with ui.ZStack():
                        ui.Rectangle(name="table")
                        with ui.VStack(style={"VStack": {"margin": SPACING * 2}}, spacing=SPACING * 2):
                            color = colors[index]
                            index = index + 1
                            ui.Triangle(name="orientation", alignment=value, style={"background_color": color})
                            ui.Label(key, style={"color": cl.black, "font_size": 8}, alignment=ui.Alignment.CENTER)

        self._caption("Line", navigate_to)
        self._text("You can use Line to draw Line shape, you can use color, border_width")

        with ui.VStack():
            self._shape_table(
                f"""ui.Line(name="default")""",
                "(Default) The Line is scaled to fit, base on the left and tip on the center right",
                100,
            )

            self._shape_table(
                """ui.Line(name="default",
                    alignment=ui.Alignment.H_CENTER,
                    style={"border_width":1, "color": cl.blue})""",
                "The Line is scaled to fit, centered top to bottom, color red and line width 1",
                100,
            )

            self._shape_table(
                """ui.Line(name="default",
                    alignment=ui.Alignment.LEFT,
                    style={"border_width":5, "color": cl("#880088")})""",
                "The Line is scaled to fit, Aligned Left , color purple and line width 5",
                100,
            )

        self._text("the Alignment define where is the line is in the Widget, always fit")
        alignments = {
            "LEFT": ui.Alignment.LEFT,
            "RIGHT": ui.Alignment.RIGHT,
            "H_CENTER": ui.Alignment.H_CENTER,
            "TOP": ui.Alignment.TOP,
            "BOTTOM": ui.Alignment.BOTTOM,
            "V_CENTER": ui.Alignment.V_CENTER,
        }
        with ui.ScrollingFrame(
            height=100,
            vertical_scrollbar_policy=ui.ScrollBarPolicy.SCROLLBAR_ALWAYS_OFF,
            style={"ScrollingFrame": {"background_color": cl.transparent}},
        ):
            with ui.HStack(height=100):
                for key, value in alignments.items():
                    with ui.ZStack():
                        ui.Rectangle(name="table")
                        with ui.VStack(style={"VStack": {"margin": SPACING * 2}}, spacing=SPACING * 2):
                            ui.Line(name="demo", alignment=value)
                            ui.Label(key, style={"color": cl.black, "font_size": 8}, alignment=ui.Alignment.CENTER)

        self._caption("FreeRectangle", navigate_to)

        self._text(
            "The free widget is the widget that is independent of the layout. It means it can be stuck to other "
            "widgets."
        )

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

        self._caption("FreeBezierCurve", navigate_to)

        self._text("Bezier curves are used to model smooth curves that can be scaled infinitely.")
        self._text(
            "FreeBezierCurve is using two widgets to get the position of the curve ends. It means it's possible to "
            "stick the curve to the layout's widgets, and the curve will follow the changes of the layout "
            "automatically."
        )

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

        ui.Spacer(height=10)
