import { __read, __spread } from "tslib";
import { createBatcher } from "./base";
/**
 * Dedupes queue items by their id field. Deduped items will be rejected
 *
 * @template Entity
 * @template CallResult
 * @param {IdBatcherParams<Entity, CallResult>} params
 */
export var createIdBatcher = function (params) {
    var entityData = new Map();
    var createIdBatcherEntryId = function (item) {
        return item.args[0][params.idField];
    };
    var prepareBatch = function (entities) {
        var dedupedEntities = new Map();
        for (var index = 0; index < entities.length; index++) {
            var entity = entities[index];
            var id = createIdBatcherEntryId(entity);
            var entityIsQueued = dedupedEntities.has(id);
            if (!entityIsQueued || !params.useFirstEntity) {
                dedupedEntities.set(id, entity);
            }
            var data = entityData.get(id);
            if (data === undefined) {
                data = {
                    id: id,
                    sources: [],
                };
                entityData.set(id, data);
            }
            data.sources.push(index);
        }
        return entities;
    };
    var finishCall = function (batchEntry, error, callResult) {
        var entityId = createIdBatcherEntryId(batchEntry);
        var sources = entityData.get(entityId).sources;
        var sourceIndex = sources.indexOf(batchEntry.index);
        var isLastSourceEntity = sourceIndex === sources.length - 1;
        if (error !== undefined) {
            batchEntry.promise.reject(error);
        }
        else if ((params.useFirstEntity && sourceIndex === 0) ||
            (!params.useFirstEntity && isLastSourceEntity) ||
            params.resolveAllDuplicates) {
            batchEntry.promise.resolve(callResult);
        }
        if (isLastSourceEntity) {
            entityData.delete(entityId);
        }
    };
    return createBatcher({
        waitTime: params.waitTime,
        prepareBatch: prepareBatch,
        addCall: function (_a) {
            var _b = _a.batchArgs, batchArgs = _b === void 0 ? [] : _b, _c = __read(_a.args, 1), newEntity = _c[0];
            return __spread(batchArgs, [
                newEntity,
            ]);
        },
        processBatch: function (entites) { return params.processBatch(entites); },
        createCallResult: function (batchResults, index) { return batchResults[index]; },
        finishCall: finishCall,
    });
};
