import { createExternallyResolvablePromise, } from "../externalPromise";
export var createBatcher = function (params) {
    var finishCall = params.finishCall !== undefined
        ? params.finishCall
        : function (batchEntry, error, callResult) {
            if (error !== undefined) {
                batchEntry.promise.reject(error);
            }
            else {
                batchEntry.promise.resolve(callResult);
            }
        };
    var batchEntries = [];
    var processBatch = function () {
        var args = batchEntries.splice(0);
        if (params.prepareBatch !== undefined) {
            args = params.prepareBatch(args);
        }
        var batchArgs;
        for (var index = 0; index < args.length; index++) {
            batchArgs = params.addCall({
                batchArgs: batchArgs,
                args: args[index].args,
                index: index,
            });
        }
        return params
            .processBatch(batchArgs)
            .then(function (res) { return ({
            error: undefined,
            res: res,
        }); })
            .catch(function (error) { return ({
            error: error,
            res: undefined,
        }); })
            .then(function (_a) {
            var error = _a.error, res = _a.res;
            for (var index = 0; index < args.length; index++) {
                var batchEntry = args[index];
                if (error !== undefined) {
                    finishCall(batchEntry, error, undefined);
                    continue;
                }
                var callResult = params.createCallResult(res, index);
                finishCall(batchEntry, undefined, callResult);
            }
            if (batchEntries.length > 0 && !params.allowParallelBatches) {
                processBatch();
            }
        });
    };
    var batchTimer;
    return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        var promise = createExternallyResolvablePromise();
        var entry = {
            args: args,
            promise: promise,
            index: batchEntries.length,
        };
        batchEntries.push(entry);
        if (batchTimer === undefined) {
            batchTimer = setTimeout(function () {
                if (params.allowParallelBatches) {
                    batchTimer = undefined;
                }
                processBatch().then(function () {
                    if (!params.allowParallelBatches) {
                        batchTimer = undefined;
                    }
                });
            }, params.waitTime);
        }
        return promise.promise;
    };
};
