# Copyright 2004-2025 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

# The displayable and style inspectors.

style _hyperlink_button is _default
style _hyperlink_button_text is _hyperlink

screen _inspector:
    layer config.interface_layer
    zorder 1010
    modal True

    frame:
        style_group ""
        right_padding 0

        has side "t c b":
            spacing gui._scale(10)

        label _("Displayable Inspector")

        if not tree:

            text _("Nothing to inspect.")

        else:

            viewport:
                scrollbars "both"
                child_size (4000, 0)
                yfill True
                xfill True
                mousewheel True

                has vbox:
                    spacing gui._scale(3)

                hbox:
                    text " ":
                        min_width gui._scale(350)
                        xmaximum gui._scale(350)

                    text _("Size"):
                        min_width gui._scale(90)
                        underline True

                    text _("Style"):
                        min_width gui._scale(225)
                        underline True

                    null width gui._scale(5)

                    text _("Location"):
                        underline True

                null height gui._scale(5)

                for depth, width, height, d in tree:

                    $ t = "  " * depth + u"\u2022 " + _inspector_repr(d)
                    $ s = __format_style(d.style.parent)


                    hbox:

                        text "[t!q]":
                            min_width gui._scale(350)

                        text "[width:.0f]x[height:.0f]":
                            min_width gui._scale(90)

                        textbutton "[s!q]":
                            style "_hyperlink_button"
                            text_min_width gui._scale(225)
                            action Show("_style_inspector", d=d)

                        null width 5

                        if d._location:
                            $ l = __format_location(d._location)

                            textbutton "[l!q]":
                                style "_hyperlink_button"
                                action _EditFile(d._location[0], d._location[1])

        hbox:
            textbutton _("Return") action Return(True)

    key "game_menu" action Return(True)

screen _style_inspector:
    layer config.interface_layer
    zorder 1020
    modal True

    frame:
        style_group ""
        right_padding 0

        has side "t c b":
            xfill True
            spacing gui._scale(10)

        $ displayable_name = _inspector_repr(d)
        label _("Inspecting Styles of [displayable_name!q]")

        $ styles = d.style.inspect()

        viewport:
            child_size (4000, 0)

            yfill True
            xfill True
            mousewheel True

            vbox:
                for i, j in enumerate(styles):

                    $ name, properties = j

                    if name is None:
                        text _("displayable:")
                    else:
                        $ style_name = __format_style(name)
                        text "style [style_name!q]:"

                    if not properties:
                        text _("        (no properties affect the displayable)")
                    elif i == (len(styles) - 1):
                        text _("        (default properties omitted)")
                    else:
                        for propname in sorted(properties):
                            $ value = __safe_repr(properties[propname])
                            text "        [propname] [value!q]"

                    null height 5

        textbutton _("Return") action Hide("_style_inspector")

    key "game_menu" action Hide("_style_inspector")


init python:

    def __format_style(name):
        return name[0] + "".join([ "[%r]" % i for i in name[1:] ])

    def __format_location(l):
        if l is None:
            return ""
        else:
            fn = l[0]
            if fn.startswith("game/"):
                fn = fn[5:]
            elif fn.startswith("renpy/common"):
                fn = fn[6:]

            return "%s:%d" % (fn, l[1])

    def __safe_repr(name):
        try:
            s = str(repr(name))
            if len(s) > 51:
                s = s[:50] + "\u2026"

            return s
        except Exception:
            return _("<repr() failed>")

    def __inspect(tree):
        renpy.context_dynamic("_window")
        store._window = False

        renpy.exports.show_screen("_inspector", transient=True, tree=tree)
        renpy.ui.interact(mouse="screen", type="screen", suppress_overlay=True, suppress_underlay=True)

    config.inspector = __inspect

    def _inspector_repr(d):
        if type(d) is renpy.display.screen.ScreenDisplayable:
            clname = "Screen"
        elif type(d) is renpy.display.layout.MultiBox:
            clname = d._classname()
        else:
            clname = type(d).__name__

        parts = [ clname ]

        info = d._repr_info()
        if info is not None:
            parts.append(info)

        if d.id is not None:
            parts.append("id %r" % d.id)

        return " ".join(parts)
