"""
Custom template filter to generate a list of FlatPage suggestions
for 404 pages.

Usage:
    {% load flatpage_suggester %}
    {% flatpage_suggester request_path %}

"""
from django import template
from django.contrib.flatpages.models import FlatPage
from django.db.models import Q
from django.template import Variable

register = template.Library()

class FlatPageSuggesterNode(template.Node):
    """
    Finds FlatPages with urls 'similar' to the given request_path.

    This template tag takes the request_path from the page_not_found 
    view (django.views.defaults), picks it apart, and attempts to 
    match existing FlatPages that have a 'similar' URL.

    For example, if the URL that resulted in a 404 was:

    /foo/bar/baz/whatever/

    This tag would look for FlatPages whose URL starts with the following:

    /foo/bar/baz/whatever/
    /foo/bar/baz/
    /foo/bar/
    /foo/

    """
    def __init__(self, request_path):
        self.request_path = Variable(request_path)

    def render(self, context):
        output = ''
        request_path = self.request_path.resolve(context)
        # Heartily discard any extensions
        request_path = request_path[:request_path.rfind('.')] 

        # Pick the path apart
        path_parts = [item for item in request_path.split('/') if len(item) > 0]

        if len(path_parts) > 0: 
            url_list = ['/%s/' % '/'.join(path_parts)]
            for x in range(1, len(path_parts) - 1):
                url = '/'.join(path_parts[:-x])
                url_list.append('/%s/' % url)
            
            # Try to find similar FlatPage objects
            q = Q(url__startswith=url_list[0]) # TODO: include the 'current' Site?
            for url in url_list[1:]:
                q.add(Q(url__startswith=url), Q.OR)
            pages = FlatPage.objects.filter(q)

            if pages.count() > 0:
                output = '<p>The following pages may be of interest:</p><ul>'
                for p in pages:
                   output += '<li><a href="%s">%s</a></li>' % (p.url, p.title)
                output += '</ul>'
       
        # No suggestions?  Start at the beginning.
        if not output:
            output = '<p>Would you like start at the <a href="/">Home Page</a>?</p>'
        
        return output

def do_flatpage_suggester(parser, token):
    """
    Parser for the flatpage_suggester Template Tag:
        {% flatpage_suggester request_path %}

    Finds FlatPages with urls 'similar' to the given request_path.
    """
    bits = list(token.split_contents())
    if len(bits) == 2:
        request_path = bits[1]
    else:
        raise template.TemplateSyntaxerror, "%r requires a request_path as an argument." % token.contents.split()[0]
    return FlatPageSuggesterNode(request_path)

register.tag('flatpage_suggester', do_flatpage_suggester)