import string

from ajax_select import LookupChannel

try:
    import ldap
    import ldap.filter
except ImportError:
    ldap = None

from django.core.exceptions import PermissionDenied
from django.template.defaultfilters import slugify
from django.utils.html import escape
from django.core.cache import cache

import app_settings

class LDAPLookup(LookupChannel):
    min_length = 3
    def ldap_attributes_to_unicode(self, ldap_attributes):
        r = {}
        for a, b in ldap_attributes.iteritems():
            if b:
                r[a] = unicode(b[0], 'utf-8')
        return r

    def get_query(self, q, request):
        if not ldap:
            return []
        cache_key = 'ldap_complete_' + slugify(q)
        result = cache.get(cache_key)
        if result is not None and False:
            return result
        connection = ldap.initialize(app_settings.LDAP_URL)
        connection.simple_bind_s(app_settings.LDAP_BIND_DN,
                app_settings.LDAP_BIND_PASSWORD)
        q = q.encode('utf-8')
        q = q.split()
        q = '*'.join(map(ldap.filter.escape_filter_chars, q))
        ldap_filter = app_settings.LDAP_COMPLETION_QUERY_FILTER.format(q)
        rid = connection.search_ext(app_settings.LDAP_BASE,
                ldap.SCOPE_SUBTREE,
                ldap_filter,
                app_settings.LDAP_COMPLETION_QUERY_ATTRIBUTES,
                sizelimit=15)
        result = []
        while True:
            try:
                r = connection.result(rid, all=0)
                if not r[1]:
                    break
                attributes = r[1][0][1]
            except ldap.SIZELIMIT_EXCEEDED:
                break
            formatter = string.Formatter()
            parsed_format = formatter.parse(app_settings.LDAP_COMPLETION_QUERY_TEMPLATE)
            ctx = self.ldap_attributes_to_unicode(attributes)
            for literal, field_name, format_spec, conversion in parsed_format:
                if field_name not in ctx:
                    ctx[field_name] = ''
            result.append(app_settings.LDAP_COMPLETION_QUERY_TEMPLATE.format(**ctx))
        cache.set(cache_key, result, 600)
        return sorted(result)

    def get_result(self, obj):
        return obj

    def format_match(self, obj):
        return escape(obj)

    def format_item_display(self, obj):
        return escape(obj)

    def check_auth(self, request):
        if not request.user.is_authenticated():
            raise PermissionDenied

