#!/usr/bin/python

import sys
from ldaptor.protocols.ldap import ldapclient, ldapsyntax, distinguishedname, ldapconnector
from ldaptor.protocols import pureber, pureldap
from ldaptor import usage, numberalloc
from twisted.internet import protocol, reactor, defer

class Search(ldapclient.LDAPClient):
    def connectionMade(self):
	d=self.bind()
	d.addCallback(self._handle_bind_success)
	d.chainDeferred(self.factory.deferred)

    def _handle_bind_success(self, x):
	matchedDN, serverSaslCreds = x
	o=ldapsyntax.LDAPEntry(client=self,
                               dn=self.factory.base)
	return numberalloc.getFreeNumber(o,
					 'uidNumber',
					 min=1000)

class SearchFactory(protocol.ClientFactory):
    protocol = Search
    def __init__(self, deferred, base):
	self.deferred=deferred
	self.base=base

    def clientConnectionFailed(self, connector, reason):
	self.deferred.errback(reason)

exitStatus=0

def error(fail):
    print fail
    print >>sys.stderr, 'fail:', fail.getErrorMessage()
    global exitStatus
    exitStatus=1

def main(base, serviceLocationOverride):
    d=defer.Deferred()
    s=SearchFactory(d, base)
    d.addCallback(lambda num: sys.stdout.write('%s\n' % repr(num)))
    d.addErrback(error)
    d.addBoth(lambda x: reactor.stop())

    dn = distinguishedname.DistinguishedName(stringValue=base)
    c = ldapconnector.LDAPConnector(reactor, dn, s, overrides=serviceLocationOverride)
    c.connect()

    reactor.run()
    sys.exit(exitStatus)

class MyOptions(usage.Options, usage.Options_service_location, usage.Options_base):
    """LDAPtor command line search utility"""

if __name__ == "__main__":
    try:
	config = MyOptions()
	config.parseOptions()
    except usage.UsageError, ue:
	sys.stderr.write('%s: %s\n' % (sys.argv[0], ue))
	sys.exit(1)

    main(config.opts['base'], config.opts['service-location'])
