#!/usr/bin/env python

import os
import sys
import string
import tempfile

import threading
import Queue

from time import sleep

_hostname = None
_username = None
_password = None
_ldapDataFile = '/tmp/kabc_ldap_threaded_record.txt'

if _hostname is None or _username is None or _password is None or _ldapDataFile is None:
    sys.stderr.write("Please first set the credentials properly.\n")
    sys.exit(1)

_ldapPreCommand = 'ldapsearch -LLL -z 0 "(Sn='
_ldapPostCommand = '*)" -h ' + _hostname + ' -x -D "'  + _username + '" -b Cn=users,DC=hq,DC=domain,DC=com' + " -w " + _password
NumberOfThreads = 5


#char = 's'
#ldapCommand = _ldapPreCommand + char + _ldapPostCommand
#x = os.system(ldapCommand)
#if x == 1024:
#    print "I'm in the exception"
#print x
#sys.exit(1)

ldap_attributes = ['dn:', 'cn:', 'sn:', 'l:', 'st:', 'title:', 'description:', 'postalCode:', 'telephoneNumber:', 'facsimileTelephoneNumber:',
                   'givenName:', 'mail:', 'homePhone:', 'mobile:', 'pager:']

try:
    writeFile = open(_ldapDataFile, 'w')
except IOError:
    sys.stderr.write("Couldn't open file %s to write.\n" % (writeFile) )
    sys.exit(1)

#print "Writing data to %s\n" % (temp_file_name)

def RecordFetcher(char):
        (temp_file_fd, temp_file_name) = tempfile.mkstemp()
        os.environ['__kabc_ldap'] = temp_file_name
        sleep(5) #Let's not thrash the exchange server ;-)
        ldapCommand = _ldapPreCommand + char + _ldapPostCommand
        if os.system(ldapCommand + "> $__kabc_ldap") != 0:
            sys.stderr.write("Couldn't execute the command %s\n" % (ldapCommand) )
            sys.exit(1)
        #temp_file_name = "/tmp/tmpnhYrps"
        try:
            readFile = open(temp_file_name, 'r')
        except IOError:
            sys.stderr.write("Couldn't open file %s to read.\n" % (readFile) )
            sys.exit(1)
            
        for record in readFile.readlines():
            if record.startswith(' '): # Remove the junk
                pass
            record = string.rstrip(record, "\n")
            for attrib in ldap_attributes:
                if record.startswith(attrib):
                    try:
                        FileLock.acquire(True)
                        
                        if ldap_attributes[0] == attrib: #This attribute is common/mandatory in all records, so we can rely on it
                           writeFile.write("\n")
                           
                        writeFile.write(record)
                        writeFile.write("\n")
                        
                    finally:
                        writeFile.flush()
                        FileLock.release()
                    break
        readFile.close()
        os.remove(temp_file_name)
        #writeFile.write("\n")
    
    
def run(request, response, func=RecordFetcher):
    while 1:
        item = request.get()
        if item is None:
            break
        (char, subChar) = item
        
        response.put(func(char+subChar) )

requestQueue = Queue.Queue()
responseQueue = Queue.Queue()

FileLock = threading.Lock()

thread_pool = [
               threading.Thread(
                                target=run,
                                args=(requestQueue, responseQueue)
                                )
               for i in range(NumberOfThreads)
               ]

for t in thread_pool: t.start()

for char in string.lowercase:
    # I know this is ugly. Too many cycles
    # But ldapsearch or exchange is restricting, the query max result limit is 1000
    for subChar in string.lowercase:
        requestQueue.put( (char, subChar) )

for t in thread_pool: requestQueue.put(None)

for t in thread_pool: t.join()

writeFile.close()

