from django.template import Library, Node, NodeList, Variable,\
    TemplateSyntaxError, VariableDoesNotExist

register = Library()

class RangeNode(Node):
    def __init__(self, var_name, start, end, step, nodelist_loop):
        self.var_name = var_name
        self.nodelist_loop = nodelist_loop

        try:
            self.start = int(start)
        except ValueError:
            self.start = Variable(start)

        try:
            self.end = int(end)
        except ValueError:
            self.end = Variable(end)

        try:
            self.step = int(step)
        except ValueError:
            self.step = Variable(step)

    def __iter__(self):
        for node in self.nodelist_loop:
            yield node
   
    def render(self, context):
        nodelist = NodeList()

        context.push()
        try:
            start = self.start.resolve(context)
        except VariableDoesNotExist:
            return ''
        except AttributeError:
            start = self.start

        try:
            end = self.end.resolve(context)
        except VariableDoesNotExist:
            return ''
        except AttributeError:
            end = self.end

        try:
            step = self.step.resolve(context)
        except VariableDoesNotExist:
            return ''
        except AttributeError:
            step = self.step

        for i in xrange(start, end, step):
            context[self.var_name] = i

            for node in self.nodelist_loop:
                nodelist.append(node.render(context))

        context.pop()
        return nodelist.render(context)

def do_range(parser, token):
    """
    Work much like forloop with a range.
    Takes both variables and constant integers.
    
    Syntax:
    {% range end as i %}
      {{ i }}
    {% endrange %}
    {% range start:end as i %}
      {{ i }}
    {% endrange %}
    {% range start:step:end as i %}
      {{ i }}
    {% endrange %}

    """

    bits = token.split_contents()
    if len(bits) != 4 or bits[2] != 'as':
        raise TemplateSyntaxError(
            "%r expected format is '[start:][step:]end as name'" % bits[0]
        )
        
    var_name = bits[3]

    rangebits = bits[1].split(':')
    if len(rangebits) == 1:
        start = 0
        end = rangebits[0]
        step = 1
    elif len(rangebits) == 2:
        start = rangebits[0]
        end = rangebits[1]
        step = 1
    elif len(rangebits) == 3:
        start = rangebits[0]
        step = rangebits[1]
        end = rangebits[2]
        
    nodelist = parser.parse(('endrange',))
    parser.delete_first_token()
    return RangeNode(var_name, start, end, step, nodelist)
do_range = register.tag('range', do_range)
