/**************************************************************************************************
 *
 * ADOBE SYSTEMS INCORPORATED
 * Copyright 2015 Adobe Systems Incorporated
 * All Rights Reserved.
 *
 * NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the
 * terms of the Adobe license agreement accompanying it.  If you have received this file from a
 * source other than Adobe, then your use, modification, or distribution of it requires the prior
 * written permission of Adobe.
 *
 **************************************************************************************************/

module.exports.ResponseCollector = function ResponseCollector(length, finish) {
    'use strict';
    this.responses = [];
    this.errors = [];
    this.pending = length;
    this.collect = function (index, err, data) {
        this.responses[index] = data;
        this.errors[index] = err;
        --this.pending;
        if (this.pending === 0 && finish) {
            finish(this.errors, this.responses);
        }
    };
};

module.exports.stripNonExistant = function stripNonExistant(object) {
    'use strict';
    const returnVal = {};
    for (const key in object) {
        if (Object.prototype.hasOwnProperty.call(object, key)) {
            if (object[key]) {
                returnVal[key] = object[key];
            }
        }
    }
    return returnVal;
};


module.exports.setLogger = function setLogger(logger) {
    'use strict';
    module.exports.log = logger;
};

module.exports.logLevel = {
    INFO: 2,
    WARNING: 1,
    ERROR: 0
};

module.exports.log = console.log;  // eslint-disable-line no-console

module.exports.throttle = function throttle(func, wait, options) {
    'use strict';
    let context, args, result;
    let timeout = null;
    let previous = 0;
    if (!options) {
        options = {};
    }
    const later = function () {
        previous = options.leading === false ? 0 : Date.now();
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) {
            context = args = null;
        }
    };
    return function () {
        const now = Date.now();
        if (!previous && options.leading === false) {
            previous = now;
        }
        const remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            result = func.apply(context, args);
            if (!timeout) {
                context = args = null;
            }
        } else if (!timeout && options.trailing !== false) {
            timeout = setTimeout(later, remaining);
        }
        return result;
    };
};

module.exports.wrapWithPostCall = function (original, postCall) {
    'use strict';
    return function () {
        const returnVal = original.apply(this, arguments);
        postCall.call(this);
        return returnVal;
    };
};

