module.exports = {
    promisify,
    promisifyObject
};

/**
 * Promisifies a function wich follows the (err, res) => {} pattern as last
 * function argument and returns the promisified version.
 *
 * @param {Function} fn Function to promisify
 * @return {Function} The promisified function
 */
function promisify(fn) {
    return function(...args) {
        let thisArg = this;
        let orgCb = args[args.length - 1];
        if (typeof orgCb !== 'function') orgCb = null;

        return new Promise(function(resolve, reject) {
            function cb(err, res) {
                if (orgCb) orgCb(err, res);
                err ? reject(err) : resolve(res);
            }

            if (orgCb)
                args[args.length - 1] = cb;
            else
                args.push(cb);

            fn.apply(thisArg, args);
        });
    };
}

/**
 * Promisifies object methods.
 *
 * @param {Object} obj Object to promisify
 * @param {Array<String>} methods Array of method names to promisify
 */
function promisifyObject(obj, methods) {
    for (let method of methods) {
        let orgMethod = obj[method];
        obj[method] = promisify(orgMethod);
    }
}