# -*- coding: utf-8 -*-
"""
    Django to Jinja
    ~~~~~~~~~~~~~~~

    Helper module that can convert django templates into Jinja2 templates.

    This file is not intended to be used as stand alone application but to
    be used as library.  To convert templates you basically create your own
    writer, add extra conversion logic for your custom template tags,
    configure your django environment and run the `convert_templates`
    function.

    Here a simple example::

        # configure django (or use settings.configure)
        import os
        os.environ['DJANGO_SETTINGS_MODULE'] = 'yourapplication.settings'
        from yourapplication.foo.templatetags.bar import MyNode

        from django2jinja import Writer, convert_templates

        def write_my_node(writer, node):
            writer.start_variable()
            writer.write('myfunc(')
            for idx, arg in enumerate(node.args):
                if idx:
                    writer.write(', ')
                writer.node(arg)
            writer.write(')')
            writer.end_variable()

        writer = Writer()
        writer.node_handlers[MyNode] = write_my_node
        convert_templates('/path/to/output/folder', writer=writer)
    
    Here is an example hos to automatically translate your django
    variables to jinja2::
        
        import re
        # List of tuple (Match pattern, Replace pattern, Exclusion pattern)
        
        var_re  = ((re.compile(r"(u|user)\.is_authenticated"), r"\1.is_authenticated()", None),
                  (re.compile(r"\.non_field_errors"), r".non_field_errors()", None),
                  (re.compile(r"\.label_tag"), r".label_tag()", None),
                  (re.compile(r"\.as_dl"), r".as_dl()", None),
                  (re.compile(r"\.as_table"), r".as_table()", None),
                  (re.compile(r"\.as_widget"), r".as_widget()", None),
                  (re.compile(r"\.as_hidden"), r".as_hidden()", None),
                  
                  (re.compile(r"\.get_([0-9_\w]+)_url"), r".get_\1_url()", None),
                  (re.compile(r"\.url"), r".url()", re.compile(r"(form|calendar).url")),
                  (re.compile(r"\.get_([0-9_\w]+)_display"), r".get_\1_display()", None),
                  (re.compile(r"loop\.counter"), r"loop.index", None),
                  (re.compile(r"loop\.revcounter"), r"loop.revindex", None),
                  (re.compile(r"request\.GET\.([0-9_\w]+)"), r"request.GET.get('\1', '')", None),
                  (re.compile(r"request\.get_host"), r"request.get_host()", None),
                  
                  (re.compile(r"\.all(?!_)"), r".all()", None),
                  (re.compile(r"\.all\.0"), r".all()[0]", None),
                  (re.compile(r"\.([0-9])($|\s+)"), r"[\1]\2", None),
                  (re.compile(r"\.items"), r".items()", None),
        )
        writer = Writer(var_re=var_re)
        
    For details about the writing process have a look at the module code.

    :copyright: (c) 2009 by the Jinja Team.
    :license: BSD.
"""
import re
import os
import sys
from jinja2.defaults import *
from django.conf import settings
from django.template import defaulttags as core_tags, loader, TextNode, \
     FilterExpression, libraries, Variable, loader_tags, TOKEN_TEXT, \
     TOKEN_VAR
from django.template.debug import DebugVariableNode as VariableNode
from django.templatetags import i18n as i18n_tags
from StringIO import StringIO


_node_handlers = {}
_resolved_filters = {}
_newline_re = re.compile(r'(?:\r\n|\r|\n)')


# Django stores an itertools object on the cycle node.  Not only is this
# thread unsafe but also a problem for the converter which needs the raw
# string values passed to the constructor to create a jinja loop.cycle()
# call from it.
_old_cycle_init = core_tags.CycleNode.__init__
def _fixed_cycle_init(self, cyclevars, variable_name=None):
    self.raw_cycle_vars = map(Variable, cyclevars)
    _old_cycle_init(self, cyclevars, variable_name)
core_tags.CycleNode.__init__ = _fixed_cycle_init


def node(cls):
    def proxy(f):
        _node_handlers[cls] = f
        return f
    return proxy


def convert_templates(output_dir, extensions=('.html', '.txt'), writer=None,
                      callback=None):
    """Iterates over all templates in the template dirs configured and
    translates them and writes the new templates into the output directory.
    """
    if writer is None:
        writer = Writer()

    def filter_templates(files):
        for filename in files:
            ifilename = filename.lower()
            for extension in extensions:
                if ifilename.endswith(extension):
                    yield filename

    def translate(f, loadname):
        template = loader.get_template(loadname)
        original = writer.stream
        writer.stream = f
        writer.body(template.nodelist)
        writer.stream = original

    if callback is None:
        def callback(template):
            print template

    for directory in settings.TEMPLATE_DIRS:
        for dirname, _, files in os.walk(directory):
            dirname = dirname[len(directory) + 1:]
            for filename in filter_templates(files):
                source = os.path.normpath(os.path.join(dirname, filename))
                target = os.path.join(output_dir, dirname, filename)
                basetarget = os.path.dirname(target)
                if not os.path.exists(basetarget):
                    os.makedirs(basetarget)
                callback(source)
                f = file(target, 'w')
                try:
                    translate(f, source)
                finally:
                    f.close()


class Writer(object):
    """The core writer class."""

    def __init__(self, stream=None, error_stream=None,
                 block_start_string=BLOCK_START_STRING,
                 block_end_string=BLOCK_END_STRING,
                 variable_start_string=VARIABLE_START_STRING,
                 variable_end_string=VARIABLE_END_STRING,
                 comment_start_string=COMMENT_START_STRING,
                 comment_end_string=COMMENT_END_STRING,
                 initial_autoescape=True,
                 use_jinja_autoescape=False,
                 custom_node_handlers=None,
                 var_re=[],
                 env=None):
        if stream is None:
            stream = sys.stdout
        if error_stream is None:
            error_stream = sys.stderr
        self.stream = stream
        self.error_stream = error_stream
        self.block_start_string = block_start_string
        self.block_end_string = block_end_string
        self.variable_start_string = variable_start_string
        self.variable_end_string = variable_end_string
        self.comment_start_string = comment_start_string
        self.comment_end_string = comment_end_string
        self.autoescape = initial_autoescape
        self.spaceless = False
        self.use_jinja_autoescape = use_jinja_autoescape
        self.node_handlers = dict(_node_handlers,
                                  **(custom_node_handlers or {}))
        self._loop_depth = 0
        self._filters_warned = set()
        self.var_re = var_re
        self.env = env

    def enter_loop(self):
        """Increments the loop depth so that write functions know if they
        are in a loop.
        """
        self._loop_depth += 1

    def leave_loop(self):
        """Reverse of enter_loop."""
        self._loop_depth -= 1

    @property
    def in_loop(self):
        """True if we are in a loop."""
        return self._loop_depth > 0

    def write(self, s):
        """Writes stuff to the stream."""
        self.stream.write(s.encode(settings.FILE_CHARSET))

    def print_expr(self, expr):
        """Open a variable tag, write to the string to the stream and close."""
        self.start_variable()
        self.write(expr)
        self.end_variable()

    def _post_open(self):
        if self.spaceless:
            self.write('- ')
        else:
            self.write(' ')

    def _pre_close(self):
        if self.spaceless:
            self.write(' -')
        else:
            self.write(' ')

    def start_variable(self):
        """Start a variable."""
        self.write(self.variable_start_string)
        self._post_open()

    def end_variable(self, always_safe=False):
        """End a variable."""
        if not always_safe and self.autoescape and \
           not self.use_jinja_autoescape:
            self.write('|e')
        self._pre_close()
        self.write(self.variable_end_string)

    def start_block(self):
        """Starts a block."""
        self.write(self.block_start_string)
        self._post_open()

    def end_block(self):
        """Ends a block."""
        self._pre_close()
        self.write(self.block_end_string)

    def tag(self, name):
        """Like `print_expr` just for blocks."""
        self.start_block()
        self.write(name)
        self.end_block()

    def variable(self, name):
        """Prints a variable.  This performs variable name transformation."""
        self.write(self.translate_variable_name(name))

    def literal(self, value):
        """Writes a value as literal."""
        value = repr(value)
        if value[:2] in ('u"', "u'"):
            value = value[1:]
        self.write(value)

    def filters(self, filters, is_block=False):
        """Dumps a list of filters."""
        want_pipe = not is_block
        for filter, args in filters:
            name = self.get_filter_name(filter)
            if name is None:
                self.warn('Could not find filter %s' % name)
                continue
            if name not in DEFAULT_FILTERS and \
               name not in self._filters_warned:
                self._filters_warned.add(name)
                self.warn('Filter %s probably doesn\'t exist in Jinja' %
                            name)
            if not want_pipe:
                want_pipe = True
            else:
                self.write('|')
            self.write(name)
            if args:
                self.write('(')
                for idx, (is_var, value) in enumerate(args):
                    if idx:
                        self.write(', ')
                    if is_var:
                        self.node(value)
                    else:
                        self.literal(value)
                self.write(')')

    def get_location(self, origin, position):
        """Returns the location for an origin and position tuple as name
        and lineno.
        """
        if hasattr(origin, 'source'):
            source = origin.source
            name = '<unknown source>'
        else:
            source = origin.loader(origin.loadname, origin.dirs)[0]
            name = origin.loadname
        lineno = len(_newline_re.findall(source[:position[0]])) + 1
        return name, lineno

    def warn(self, message, node=None):
        """Prints a warning to the error stream."""
        if node is not None and hasattr(node, 'source'):
            filename, lineno = self.get_location(*node.source)
            message = '[%s:%d] %s' % (filename, lineno, message)
        print >> self.error_stream, message

    def translate_variable_name(self, var):
        """Performs variable name translation."""
        if self.in_loop and var == 'forloop' or var.startswith('forloop.'):
            var = var[3:]
        
        for reg, rep, unless in self.var_re:
            no_unless = unless and unless.search(var) or True
            if reg.search(var) and no_unless:
                var = reg.sub(rep, var)
                break
        return var

    def get_filter_name(self, filter):
        """Returns the filter name for a filter function or `None` if there
        is no such filter.
        """
        if filter not in _resolved_filters:
            for library in libraries.values():
                for key, value in library.filters.iteritems():
                    _resolved_filters[value] = key
        return _resolved_filters.get(filter, None)

    def node(self, node):
        """Invokes the node handler for a node."""
        for cls, handler in self.node_handlers.iteritems():
            if type(node) is cls or type(node).__name__ == cls:
                handler(self, node)
                break
        else:
            self.warn('Untranslatable node %s.%s found' % (
                node.__module__,
                node.__class__.__name__
            ), node)

    def body(self, nodes):
        """Calls node() for every node in the iterable passed."""
        for node in nodes:
            self.node(node)


@node(TextNode)
def text_node(writer, node):
    writer.write(node.s)


@node(Variable)
def variable(writer, node):
    if node.translate:
        writer.warn('i18n system used, make sure to install translations', node)
        writer.write('_(')
    if node.literal is not None:
        writer.literal(node.literal)
    else:
        writer.variable(node.var)
    if node.translate:
        writer.write(')')


@node(VariableNode)
def variable_node(writer, node):
    writer.start_variable()
    if node.filter_expression.var.var == 'block.super' \
       and not node.filter_expression.filters:
        writer.write('super()')
    else:
        writer.node(node.filter_expression)
    writer.end_variable()


@node(FilterExpression)
def filter_expression(writer, node):
    writer.node(node.var)
    writer.filters(node.filters)


@node(core_tags.CommentNode)
def comment_tag(writer, node):
    pass


@node(core_tags.DebugNode)
def comment_tag(writer, node):
    writer.warn('Debug tag detected.  Make sure to add a global function '
                'called debug to the namespace.', node=node)
    writer.print_expr('debug()')


@node(core_tags.ForNode)
def for_loop(writer, node):
    writer.start_block()
    writer.write('for ')
    for idx, var in enumerate(node.loopvars):
        if idx:
            writer.write(', ')
        writer.variable(var)
    writer.write(' in ')
    if node.is_reversed:
        writer.write('(')
    writer.node(node.sequence)
    if node.is_reversed:
        writer.write(')|reverse')
    writer.end_block()
    writer.enter_loop()
    writer.body(node.nodelist_loop)
    writer.leave_loop()
    writer.tag('endfor')


@node(core_tags.IfNode)
def if_condition(writer, node):
    writer.start_block()
    writer.write('if ')
    join_with = 'and'
    if node.link_type == core_tags.IfNode.LinkTypes.or_:
        join_with = 'or'
    
    for idx, (ifnot, expr) in enumerate(node.bool_exprs):
        if idx:
            writer.write(' %s ' % join_with)
        if ifnot:
            writer.write('not ')
        writer.node(expr)
    writer.end_block()
    writer.body(node.nodelist_true)
    if node.nodelist_false:
        writer.tag('else')
        writer.body(node.nodelist_false)
    writer.tag('endif')


@node(core_tags.IfEqualNode)
def if_equal(writer, node):
    writer.start_block()
    writer.write('if ')
    writer.node(node.var1)
    if node.negate:
        writer.write(' != ')
    else:
        writer.write(' == ')
    writer.node(node.var2)
    writer.end_block()
    writer.body(node.nodelist_true)
    if node.nodelist_false:
        writer.tag('else')
        writer.body(node.nodelist_false)
    writer.tag('endif')


@node(loader_tags.BlockNode)
def block(writer, node):
    writer.tag('block ' + node.name.replace('-', '_').rstrip('_'))
    node = node
    while node.parent is not None:
        node = node.parent
    writer.body(node.nodelist)
    writer.tag('endblock')


@node(loader_tags.ExtendsNode)
def extends(writer, node):
    writer.start_block()
    writer.write('extends ')
    if node.parent_name_expr:
        writer.node(node.parent_name_expr)
    else:
        writer.literal(node.parent_name)
    writer.end_block()
    writer.body(node.nodelist)


@node(loader_tags.ConstantIncludeNode)
@node(loader_tags.IncludeNode)
def include(writer, node):
    writer.start_block()
    writer.write('include ')
    if hasattr(node, 'template'):
        writer.literal(node.template.name)
    else:
        writer.node(node.template_name)
    writer.end_block()


@node(core_tags.CycleNode)
def cycle(writer, node):
    if not writer.in_loop:
        writer.warn('Untranslatable free cycle (cycle outside loop)', node=node)
        return
    if node.variable_name is not None:
        writer.start_block()
        writer.write('set %s = ' % node.variable_name)
    else:
        writer.start_variable()
    writer.write('loop.cycle(')
    for idx, var in enumerate(node.raw_cycle_vars):
        if idx:
            writer.write(', ')
        writer.node(var)
    writer.write(')')
    if node.variable_name is not None:
        writer.end_block()
    else:
        writer.end_variable()


@node(core_tags.FilterNode)
def filter(writer, node):
    writer.start_block()
    writer.write('filter ')
    writer.filters(node.filter_expr.filters, True)
    writer.end_block()
    writer.body(node.nodelist)
    writer.tag('endfilter')


@node(core_tags.AutoEscapeControlNode)
def autoescape_control(writer, node):
    original = writer.autoescape
    writer.autoescape = node.setting
    writer.body(node.nodelist)
    writer.autoescape = original


@node(core_tags.SpacelessNode)
def spaceless(writer, node):
    original = writer.spaceless
    writer.spaceless = True
    writer.warn('entering spaceless mode with different semantics', node)
    # do the initial stripping
    nodelist = list(node.nodelist)
    if nodelist:
        if isinstance(nodelist[0], TextNode):
            nodelist[0] = TextNode(nodelist[0].s.lstrip())
        if isinstance(nodelist[-1], TextNode):
            nodelist[-1] = TextNode(nodelist[-1].s.rstrip())
    writer.body(nodelist)
    writer.spaceless = original


@node(core_tags.TemplateTagNode)
def template_tag(writer, node):
    tag = {
        'openblock':            writer.block_start_string,
        'closeblock':           writer.block_end_string,
        'openvariable':         writer.variable_start_string,
        'closevariable':        writer.variable_end_string,
        'opencomment':          writer.comment_start_string,
        'closecomment':         writer.comment_end_string,
        'openbrace':            '{',
        'closebrace':           '}'
    }.get(node.tagtype)
    if tag:
        writer.start_variable()
        writer.literal(tag)
        writer.end_variable()


@node(core_tags.URLNode)
def url_tag(writer, node):
    writer.warn('url node used.  make sure to provide a proper url() '
                'function', node)
    if node.asvar:
        writer.start_block()
        writer.write('set %s = ' % node.asvar)
    else:
        writer.start_variable()
    autoescape = writer.autoescape
    writer.write('url(')
    writer.literal(node.view_name)
    for arg in node.args:
        writer.write(', ')
        writer.node(arg)
    for key, arg in node.kwargs.items():
        writer.write(', %s=' % key)
        writer.node(arg)
    writer.write(')')
    if node.asvar:
        writer.end_block()
    else:
        writer.end_variable()


@node(core_tags.WidthRatioNode)
def width_ratio(writer, node):
    writer.warn('widthratio expanded into formula.  You may want to provide '
                'a helper function for this calculation', node)
    writer.start_variable()
    writer.write('(')
    writer.node(node.val_expr)
    writer.write(' / ')
    writer.node(node.max_expr)
    writer.write(' * ')
    writer.write(str(int(node.max_width)))
    writer.write(')|round|int')
    writer.end_variable(always_safe=True)


@node(core_tags.WithNode)
def with_block(writer, node):
    writer.warn('with block expanded into set statement.  This could cause '
                'variables following that block to be overriden.', node)
    writer.start_block()
    writer.write('set %s = ' % node.name)
    writer.node(node.var)
    writer.end_block()
    writer.body(node.nodelist)


@node(core_tags.RegroupNode)
def regroup(writer, node):
    if node.expression.var.literal:
        writer.warn('literal in groupby filter used.   Behavior in that '
                    'situation is undefined and translation is skipped.', node)
        return
    elif node.expression.filters:
        writer.warn('filters in groupby filter used.   Behavior in that '
                    'situation is undefined which is most likely a bug '
                    'in your code.  Filters were ignored.', node)
    writer.start_block()
    writer.write('set %s = ' % node.var_name)
    writer.node(node.target)
    writer.write('|groupby(')
    writer.literal(node.expression.var.var)
    writer.write(')')
    writer.end_block()


@node(core_tags.LoadNode)
def warn_load(writer, node):
    writer.warn('load statement used which was ignored on conversion', node)


@node(i18n_tags.GetAvailableLanguagesNode)
def get_available_languages(writer, node):
    writer.warn('make sure to provide a get_available_languages function', node)
    writer.tag('set %s = get_available_languages()' %
               writer.translate_variable_name(node.variable))


@node(i18n_tags.GetCurrentLanguageNode)
def get_current_language(writer, node):
    writer.warn('make sure to provide a get_current_language function', node)
    writer.tag('set %s = get_current_language()' %
               writer.translate_variable_name(node.variable))


@node(i18n_tags.GetCurrentLanguageBidiNode)
def get_current_language_bidi(writer, node):
    writer.warn('make sure to provide a get_current_language_bidi function', node)
    writer.tag('set %s = get_current_language_bidi()' %
               writer.translate_variable_name(node.variable))


@node(i18n_tags.TranslateNode)
def simple_gettext(writer, node):
    writer.warn('i18n system used, make sure to install translations', node)
    writer.start_variable()
    writer.write('_(')
    writer.node(node.value)
    writer.write(')')
    writer.end_variable()


@node(i18n_tags.BlockTranslateNode)
def translate_block(writer, node):
    first_var = []
    variables = set()

    def touch_var(name):
        variables.add(name)
        if not first_var:
            first_var.append(name)

    def dump_token_list(tokens):
        for token in tokens:
            if token.token_type == TOKEN_TEXT:
                writer.write(token.contents)
            elif token.token_type == TOKEN_VAR:
                writer.print_expr(token.contents)
                touch_var(token.contents)

    writer.warn('i18n system used, make sure to install translations', node)
    writer.start_block()
    writer.write('trans')
    idx = -1
    for idx, (key, var) in enumerate(node.extra_context.items()):
        if idx:
            writer.write(',')
        writer.write(' %s=' % key)
        touch_var(key)
        writer.node(var.filter_expression)

    have_plural = False
    plural_var = None
    if node.plural and node.countervar and node.counter:
        have_plural = True
        plural_var = node.countervar
        if plural_var not in variables:
            if idx > -1:
                writer.write(',')
            touch_var(plural_var)
            writer.write(' %s=' % plural_var)
            writer.node(node.counter)

    writer.end_block()
    dump_token_list(node.singular)
    if node.plural and node.countervar and node.counter:
        writer.start_block()
        writer.write('pluralize')
        if node.countervar != first_var[0]:
            writer.write(' ' + node.countervar)
        writer.end_block()
        dump_token_list(node.plural)
    writer.tag('endtrans')

@node("SimpleNode")
def simple_tag(writer, node):
    """Check if the simple tag exist as a filter in """
    name = node.tag_name
    if writer.env and \
       name not in writer.env.filters and \
       name not in writer._filters_warned:
        writer._filters_warned.add(name)
        writer.warn('Filter %s probably doesn\'t exist in Jinja' %
                    name)
        
    if not node.vars_to_resolve:
        # No argument, pass the request
        writer.start_variable()
        writer.write('request|')
        writer.write(name)
        writer.end_variable()
        return 
    
    first_var =  node.vars_to_resolve[0]
    args = node.vars_to_resolve[1:]
    writer.start_variable()
    
    # Copied from Writer.filters()
    writer.node(first_var)
    
    writer.write('|')
    writer.write(name)
    if args:
        writer.write('(')
        for idx, var in enumerate(args):
            if idx:
                writer.write(', ')
            if var.var:
                writer.node(var)
            else:
                writer.literal(var.literal)
        writer.write(')')
    writer.end_variable()   

# get rid of node now, it shouldn't be used normally
del node
