# basic.py - basic benchmarks adapted from Genshi
# Copyright (C) 2006 Edgewall Software
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in
#     the documentation and/or other materials provided with the
#     distribution.
#  3. The name of the author may not be used to endorse or promote
#     products derived from this software without specific prior
#     written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from io import StringIO
import sys
import timeit


__all__ = [
    "mako",
    "mako_inheritance",
    "jinja2",
    "jinja2_inheritance",
    "cheetah",
    "django",
    "myghty",
    "genshi",
    "kid",
]

# Templates content and constants
TITLE = "Just a test"
USER = "joe"
ITEMS = ["Number %d" % num for num in range(1, 15)]


def genshi(dirname, verbose=False):
    from genshi.template import TemplateLoader

    loader = TemplateLoader([dirname], auto_reload=False)
    template = loader.load("template.html")

    def render():
        data = dict(title=TITLE, user=USER, items=ITEMS)
        return template.generate(**data).render("xhtml")

    if verbose:
        print(render())
    return render


def myghty(dirname, verbose=False):
    from myghty import interp

    interpreter = interp.Interpreter(component_root=dirname)

    def render():
        data = dict(title=TITLE, user=USER, items=ITEMS)
        buffer = StringIO()
        interpreter.execute(
            "template.myt", request_args=data, out_buffer=buffer
        )
        return buffer.getvalue()

    if verbose:
        print(render())
    return render


def mako(dirname, verbose=False):
    from mako.template import Template
    from mako.lookup import TemplateLookup

    lookup = TemplateLookup(directories=[dirname], filesystem_checks=False)
    template = lookup.get_template("template.html")

    def render():
        return template.render(title=TITLE, user=USER, list_items=ITEMS)

    if verbose:
        print(template.code + " " + render())
    return render


mako_inheritance = mako


def jinja2(dirname, verbose=False):
    from jinja2 import Environment, FileSystemLoader

    env = Environment(loader=FileSystemLoader(dirname))
    template = env.get_template("template.html")

    def render():
        return template.render(title=TITLE, user=USER, list_items=ITEMS)

    if verbose:
        print(render())
    return render


jinja2_inheritance = jinja2


def cheetah(dirname, verbose=False):
    from Cheetah.Template import Template

    filename = os.path.join(dirname, "template.tmpl")
    template = Template(file=filename)

    def render():
        template.__dict__.update(
            {"title": TITLE, "user": USER, "list_items": ITEMS}
        )
        return template.respond()

    if verbose:
        print(dir(template))
        print(template.generatedModuleCode())
        print(render())
    return render


def django(dirname, verbose=False):
    from django.conf import settings

    settings.configure(TEMPLATE_DIRS=[os.path.join(dirname, "templates")])
    from django import template, templatetags
    from django.template import loader

    templatetags.__path__.append(os.path.join(dirname, "templatetags"))
    tmpl = loader.get_template("template.html")

    def render():
        data = {"title": TITLE, "user": USER, "items": ITEMS}
        return tmpl.render(template.Context(data))

    if verbose:
        print(render())
    return render


def kid(dirname, verbose=False):
    import kid

    kid.path = kid.TemplatePath([dirname])
    template = kid.Template(file="template.kid")

    def render():
        template = kid.Template(
            file="template.kid", title=TITLE, user=USER, items=ITEMS
        )
        return template.serialize(output="xhtml")

    if verbose:
        print(render())
    return render


def run(engines, number=2000, verbose=False):
    basepath = os.path.abspath(os.path.dirname(__file__))
    for engine in engines:
        dirname = os.path.join(basepath, engine)
        if verbose:
            print("%s:" % engine.capitalize())
            print("--------------------------------------------------------")
        else:
            sys.stdout.write("%s:" % engine.capitalize())
        t = timeit.Timer(
            setup='from __main__ import %s; render = %s(r"%s", %s)'
            % (engine, engine, dirname, verbose),
            stmt="render()",
        )

        time = t.timeit(number=number) / number
        if verbose:
            print("--------------------------------------------------------")
        print("%.2f ms" % (1000 * time))
        if verbose:
            print("--------------------------------------------------------")


if __name__ == "__main__":
    engines = [arg for arg in sys.argv[1:] if arg[0] != "-"]
    if not engines:
        engines = __all__

    verbose = "-v" in sys.argv

    if "-p" in sys.argv:
        try:
            import hotshot, hotshot.stats

            prof = hotshot.Profile("template.prof")
            benchtime = prof.runcall(run, engines, number=100, verbose=verbose)
            stats = hotshot.stats.load("template.prof")
        except ImportError:
            import cProfile, pstats

            stmt = "run(%r, number=%r, verbose=%r)" % (engines, 1000, verbose)
            cProfile.runctx(stmt, globals(), {}, "template.prof")
            stats = pstats.Stats("template.prof")
        stats.strip_dirs()
        stats.sort_stats("time", "calls")
        stats.print_stats()
    else:
        run(engines, verbose=verbose)
