# Copyright 2004-2014 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.

# This file contains code that helps support the development of Ren'Py
# games.

# List styles.

style list is default
style list_box is vbox
style list_row is default
style list_row_box is hbox
style list_spacer is default
style list_text is default

style list_row:
    xfill True
    ymargin 0
    background "#eee"
    hover_background "#fff"
    selected_background "#cce"

init python:
    style.list_row[1].background = "#ddd"
    style.list_row[1].hover_background = "#fff"
    style.list_row[1].selected_background = "#cce"

style list_text:
    color "#000"
    size 14

style list_spacer:
    xminimum 15

screen _developer:

    zorder 1001
    modal True

    frame:
        style_group "_developer"

        align (.025, .05)

        has vbox

        label _(u"Developer Menu")

        textbutton _("Reload Game (Shift+R)"):
            action ui.callsinnewcontext("_save_reload_game")
        textbutton _("Console (Shift+O)"):
            action [ Hide("_developer"), _console.enter ]
        textbutton _("Variable Viewer"):
            action ui.callsinnewcontext("_debugger_screen")
        textbutton _("Theme Test"):
            action ui.callsinnewcontext("_theme_test")
        textbutton _("Image Location Picker"):
            action ui.callsinnewcontext("_image_location_picker")
        textbutton _("Filename List"):
            action ui.callsinnewcontext("_filename_list")

        if not renpy.get_screen("_image_load_log"):
            textbutton _("Show Image Load Log"):
                action Show("_image_load_log")
        else:
            textbutton _("Hide Image Load Log"):
                action Hide("_image_load_log")

        null height 15

        textbutton _(u"Return"):
            action Hide("_developer")
            size_group "developer"

style _developer_frame is _frame
style _developer_vbox is _vbox

style _developer_button is _button:
    size_group "developer"

style _developer_button_text is _button_text
style _developer_label is _label
style _developer_label_text is _label_text


label _debugger_screen:

    python hide:

        ui.window(style=style.gm_root)
        ui.null()

        ui.frame(ymargin=10, xmargin=10, style=style.menu_frame)
        ui.side(['t', 'c', 'r', 'b'])

        layout.label(_("Variable Viewer"), None)

        entries = [ ]

        ebc = store.__dict__.ever_been_changed
        ebc = list(ebc)
        ebc.sort()

        ebc.remove("nvl_list")

        import repr
        aRepr = repr.Repr()
        aRepr.maxstring = 40

        for var in ebc:
            if not hasattr(store, var):
                continue

            if var.startswith("__00"):
                continue

            if var.startswith("_") and not var.startswith("__"):
                continue

            val = aRepr.repr(getattr(store, var))
            s = (var + " = " + val)
            s = s.replace("{", "{{")
            s = s.replace("[", "[[")
            entries.append((0, s))

        if entries:
            vp = ui.viewport(mousewheel=True)
            layout.list(entries)
            ui.bar(adjustment=vp.yadjustment, style='vscrollbar')
        else:
            layout.prompt(_("No variables have changed since the game started."), None)
            ui.null()

        layout.button(_(u"Return to the developer menu"), None, clicked=ui.returns(True))

        ui.close()

        ui.interact()

    return

label _theme_test:

    python hide:

        # Never gets pickled
        def role(b):
            if b:
                return "selected_"
            else:
                return ""

        toggle_var = True
        adj = ui.adjustment(100, 25, page=25, adjustable=True)

        while True:

            ui.window(style=style.gm_root)
            ui.null()

            # Buttons
            ui.hbox(box_spacing=10, xpos=10, ypos=10)

            ui.vbox(box_spacing=10)

            sg = "theme_test"

            ui.frame(style='menu_frame')
            ui.vbox()
            layout.label("Button", None)
            ui.textbutton("Button", size_group=sg, clicked=ui.returns("gndn"))
            ui.textbutton("Button (Selected)", size_group=sg, clicked=ui.returns("gndn"), role=role(True))
            ui.textbutton("Small", clicked=ui.returns("gndn"), style='small_button')
            ui.close()

            ui.frame(style='menu_frame')
            ui.vbox()
            layout.label("Radio Button", None)
            ui.textbutton("True", size_group=sg, clicked=ui.returns("set"), role=role(toggle_var), style='radio_button')
            ui.textbutton("False", size_group=sg, clicked=ui.returns("unset"), role=role(not toggle_var), style='radio_button')
            ui.close()

            ui.frame(style='menu_frame')
            ui.vbox()
            layout.label("Check Button", None)
            ui.textbutton("Check Button", size_group=sg, clicked=ui.returns("toggle"), role=role(toggle_var), style='check_button')
            ui.close()

            ui.frame(style='menu_frame')
            ui.vbox(box_spacing=2)
            ui.bar(adjustment=adj, style='bar', xmaximum=200)
            ui.bar(adjustment=adj, style='slider', xmaximum=200)
            ui.bar(adjustment=adj, style='scrollbar', xmaximum=200)
            ui.close()

            ui.close() # vbox

            ui.frame(style='menu_frame')
            ui.hbox(box_spacing=2)
            ui.bar(adjustment=adj, style='vbar', ymaximum=200)
            ui.bar(adjustment=adj, style='vslider', ymaximum=200)
            ui.bar(adjustment=adj, style='vscrollbar', ymaximum=200)
            ui.close()

            ui.frame(style='menu_frame', xmaximum=0.95)
            ui.vbox(box_spacing=20)
            layout.prompt("This is a prompt. We've made this text long enough to wrap around so it fills multiple lines.", None)
            ui.close()

            ui.close() # hbox

            ui.frame(style='menu_frame', xalign=.01, yalign=.99)
            ui.textbutton(_("Return to the developer menu"), clicked=ui.returns("return"))

            rv = ui.interact()
            if rv == "return":
                break

            elif rv == "set":
                toggle_var = True
            elif rv == "unset":
                toggle_var = False
            elif rv == "toggle":
                toggle_var = not toggle_var

    return


init -1050 python:
    config.missing_background = "black"

style _missing_frame is _frame:
    xalign 0.5
    yalign 0.0
    background "#0004"
    xpadding 5
    ypadding 5

style _missing_text is _text:
    color "#fff"
    xalign 0.5

screen _missing_images:
    zorder -1050
    $ missing = renpy.context().__missing

    if missing:

        frame:
            style "_missing_frame"

            has vbox

            text _("{b}Missing Images{/b}"):
                style "_missing_text"

            for what in sorted(missing.values()):

                text "[what!q]":
                    style "_missing_text"

init 1050 python:

    if config.developer:

        # This is used to indicate that a scene has just occured,
        # and so if the next thing is a missing_show, we should
        # blank the screen.
        __missing_scene = False

        # This returns the __missing dictionary from the current
        # context object.
        def __missing():
            try:
                return renpy.context().__missing
            except AttributeError:
                rv = dict()
                renpy.context().__missing = rv
                return rv

        def __missing_show_callback(name, what, layer):
            if layer != 'master':
                return False

            global __missing_scene
            if __missing_scene:
                renpy.show(name, what=config.missing_background)
            __missing_scene = False

            what = " ".join(what)
            __missing()[name[0]] = what
            return True

        def __missing_hide_callback(name, layer):
            if layer != 'master':
                return False

            global __missing_scene
            __missing_scene = False
            __missing().pop(name[0], None)
            return True

        def __missing_scene_callback(layer):
            if layer != 'master':
                return False

            global __missing_scene
            __missing_scene = True
            __missing().clear()

            return True

        config.missing_scene = __missing_scene_callback
        config.missing_show = __missing_show_callback
        config.missing_hide = __missing_hide_callback

        config.start_callbacks.append(Show("_missing_images"))


init -1050 python:

    class __FPSMeter(object):

        def __init__(self):
            self.last_frames = None
            self.last_time = None

        def __call__(self, st, at):

            if self.last_time is not None:
                frames = config.frames - self.last_frames
                time = st - self.last_time

                text = "FPS: %.1f" % (frames / time)

            else:
                text = "FPS: --.-"

            self.last_frames = config.frames
            self.last_time = st

            return Text(text, xalign=1.0), .5

label _fps_meter:

    python hide:
        def fps_overlay():
            ui.add(DynamicDisplayable(__FPSMeter()))

        # We normally don't want to change this at runtime... but here
        # it's okay, because we don't want to save the FPS meter anyway.
        #
        # Do as I say, not as I do.
        config.overlay_functions.append(fps_overlay)

    return


init python:

    # This is a displayable that can keep track of the mouse coordinates,
    # and show them to the user.
    class __ImageLocationPicker(renpy.Displayable):

        def __init__(self, fn, **kwargs):
            super(__ImageLocationPicker, self).__init__(**kwargs)

            self.child = Image(fn)

            self.mouse = None
            self.point1 = None
            self.point2 = None

        def render(self, width, height, st, at):
            rv = renpy.Render(width, height)

            cr = renpy.render(self.child, width, height, st, at)
            rv.blit(cr, (0, 0))

            text = [ ]


            if self.point1 and self.point2 and not self.point1 == self.point2:
                x1, y1 = self.point1
                x2, y2 = self.point2

                x1 = min(x1, cr.width)
                x2 = min(x2, cr.width)
                y1 = min(y1, cr.height)
                y2 = min(y2, cr.height)

                minx = min(x1, x2)
                miny = min(y1, y2)
                maxx = max(x1, x2)
                maxy = max(y1, y2)

                w = maxx - minx
                h = maxy - miny

                if w and h:

                    sr = renpy.render(Solid("#0ff4"), w, h, st, at)
                    rv.blit(sr, (minx, miny))

                    # text.append("Imagemap rectangle: %r" % ((minx, miny, maxx, maxy),))
                    text.append(__("Rectangle: %r") % ((minx, miny, w, h),))

            if self.mouse:
                mx, my = self.mouse
                if mx < cr.width and my < cr.height:
                    text.append(__("Mouse position: %r") % (self.mouse,))

            text.append(__("Right-click or escape to quit."))

            td = Text("\n".join(text), size=14, color="#fff", outlines=[ (1, "#000", 0, 0 ) ])
            tr = renpy.render(td, width, height, st, at)

            rv.blit(tr, (0, height - tr.height))

            return rv

        def event(self, ev, x, y, st):
            import pygame

            self.mouse = (x, y)
            renpy.redraw(self, 0)

            if ev.type == pygame.MOUSEBUTTONDOWN and ev.button == 1:
                self.point1 = (x, y)
                self.point2 = (x, y)

            elif ev.type == pygame.MOUSEMOTION and ev.buttons[0]:
                self.point2 = (x, y)

            elif ev.type == pygame.MOUSEBUTTONUP and ev.button == 1:
                self.point2 = (x, y)


label _image_location_picker:

    scene black

    python hide:

        image_files = [
            fn
            for dir, fn in renpy.loader.listdirfiles()
            if fn.lower().endswith(".jpg") or fn.lower().endswith(".png")
            if not fn[0] == "_"
            ]

        image_files.sort()

        xadjustment = ui.adjustment()
        yadjustment = ui.adjustment()

        while True:

            ui.frame()
            ui.vbox()

            layout.label(_(u"Image Location Picker"), None)

            ui.textbutton(_(u"Done"), clicked=ui.returns(False), size_group="files")

            ui.side(['c', 'b', 'r'], spacing=5)
            vp = ui.viewport(xadjustment=xadjustment, yadjustment=yadjustment, mousewheel=True)

            ui.vbox()

            for fn in image_files:
                ui.button(clicked=ui.returns(fn), size_group="files", xminimum=1.0)
                ui.text(fn.replace("{", "{{").replace("[", "[["), style="button_text", xalign=0.0)

            ui.close()

            ui.bar(adjustment=xadjustment, style='scrollbar')
            ui.bar(adjustment=yadjustment, style='vscrollbar')
            ui.close()

            ui.close()

            rv = ui.interact()

            if rv is False:
                renpy.jump("_image_location_picker_done")

            # Now, allow the user to pick the image.

            ui.keymap(game_menu=ui.returns(True))
            ui.add(__ImageLocationPicker(rv))
            ui.interact()

        renpy.jump("_image_location_picker")

label _image_location_picker_done:
    return


label _filename_list:

    python hide:
        import os
        f = file("files.txt", "w")

        for dirname, dirs, files in os.walk(config.gamedir):

            dirs.sort()
            files.sort()

            for fn in files:
                fn = os.path.join(dirname, fn)
                fn = fn[len(config.gamedir) + 1:]
                print >>f, fn.encode("utf-8", "replace")
                print fn.encode("utf-8", "replace")

        f.close()

        renpy.launch_editor(["files.txt"], transient=1)

    return


init python:
    def _image_load_log_function(st, at):

        ill = list(renpy.get_image_load_log(3))

        vbox = VBox()

        for when, filename, preload in ill:
            if preload:
                color="#ffffff"
            else:
                color="#ffcccc"

            vbox.add(Text(filename.replace("{", "{{").replace("[", "[["), size=12, color=color, style="_default"))

        rv = Window(vbox, style="_frame", background="#0004", xpadding=5, ypadding=5, xminimum=200)
        return rv, .25

screen _image_load_log:
    zorder 1000

    add DynamicDisplayable(_image_load_log_function)



init python:
    config.underlay.append(im.Tile("_transparent_tile.png"))
