const ldap = require('ldapjs');
const promisifyObject = require('./promisify').promisifyObject;

module.exports = {
    createClient,
    Change: ldap.Change
};

/**
 * Creates a promisified version of LDAP client.
 *
 * @param {Object} opts Client options
 * @return {Client} The promisified LDAP client
 */
function createClient(opts) {
    let client = ldap.createClient(opts);
    promisifyObject(client, [
        'bind',
        'add',
        'compare',
        'del',
        'exop',
        'modify',
        'modifyDN',
        'search',
        'starttls',
        'unbind'
    ]);

    Object.assign(client, {
        async searchForeach(base, options, eachFn, controls) {
            let res = await this.search(base, options);

            await new Promise((resolve, reject) => {
                res.on('error', err => {
                    if (err.name === 'NoSuchObjectError')
                        err = new Error(`Object '${base}' does not exist`);
                    reject(err);
                });
                res.on('searchEntry', e => eachFn(e.object));
                res.on('end', resolve);
            });
        },

        async searchAll(base, options, controls) {
            let elements = [];
            await this.searchForeach(base, options,
                o => elements.push(o), controls);
            return elements;
        },

        async searchOne(base, options, controls) {
            let object;
            await this.searchForeach(base, options,
                o => object = o, controls);
            return object;
        }
    });

    return client;
}