from django.contrib.auth.models import User
from django.template.base import Library, Node, NodeList, TemplateSyntaxError, Variable, VariableDoesNotExist


register = Library()

class IfPermittedNode(Node):
    def __init__(self, perm, obj, nodelist_true, nodelist_false=None, user_obj=None):
        self.perm, self.obj = perm, Variable(obj)
        self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
        if user_obj is not None:
            self.user_obj = Variable(user_obj)
        else:
            self.user_obj = None
    
    def render(self, context):
        # If obj doesn't exist, resolve will raise VariableDoesNotExist; we want this.
        obj = self.obj.resolve(context)
        if self.user_obj:
            user_obj = self.obj.resolve(context)
        else:
            req = context.get('request', None)
            user_obj = getattr(req, 'user', None)
        if not isinstance(user_obj, User):
            raise VariableDoesNotExist("ifpermitted requires either the 'request' context processor or an explicit user object")
        if user_obj.has_perm(self.perm, obj):
            return self.nodelist_true.render(context)
        elif self.nodelist_false:
            return self.nodelist_false.render(context)
        return ''

@register.tag
def ifpermitted(parser, token):
    bits = list(token.split_contents())
    user_obj = None
    if len(bits) == 3:
        (tag_name, perm, obj) = bits
    elif len(bits) == 4:
        (tag_name, perm, obj, user_obj) = bits
    else:
        raise TemplateSyntaxError("%s takes either two or three arguments" % bits[0])
    
    if not (perm[0] == perm[-1] and perm[0] in ('"', "'")):
        raise TemplateSyntaxError("%s permission argument should be in quotes" % bits[0])
    nodelist_true = parser.parse(('else', 'endifpermitted'))
    token = parser.next_token()
    if token.contents == 'else':
        nodelist_false = parser.parse(('endifpermitted',))
        parser.delete_first_token()
    else:
        nodelist_false = NodeList()
    return IfPermittedNode(perm[1:-1], obj, nodelist_true, nodelist_false, user_obj)
