"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const operators_1 = require("rxjs/operators");
const metadata_1 = require("../../../decorator/metadata");
const helper_1 = require("../../../helper");
const logger_1 = require("../../../logger/logger");
const mapper_1 = require("../../../mapper");
const get_table_name_function_1 = require("../../get-table-name.function");
const batch_write_utils_1 = require("./batch-write-utils");
const MAX_BATCH_WRITE_ITEMS = 25;
const DEFAULT_TIME_SLOT = 1000;
class BatchWriteSingleTableRequest {
    constructor(dynamoRx, modelClazz) {
        this.createDeleteRequest = (item) => ({ DeleteRequest: { Key: this.toKey(item) } });
        this.createPutRequest = (item) => ({ PutRequest: { Item: mapper_1.toDb(item, this.modelClazz) } });
        this.logger = logger_1.createLogger('dynamo.request.BatchWriteSingleTableRequest', modelClazz);
        this.dynamoRx = dynamoRx;
        if (modelClazz === null || modelClazz === undefined) {
            throw new Error("please provide the model clazz for the request, won't work otherwise");
        }
        this.modelClazz = modelClazz;
        this.metadata = metadata_1.metadataForClass(this.modelClazz);
        if (!this.metadata.modelOptions) {
            throw new Error('given ModelConstructor has no @Model decorator');
        }
        this.tableName = get_table_name_function_1.getTableName(this.metadata);
        this.params = {
            RequestItems: {
                [this.tableName]: [],
            },
        };
    }
    get toKey() {
        if (!this.keyFn) {
            this.keyFn = mapper_1.createToKeyFn(this.modelClazz);
        }
        return this.keyFn;
    }
    returnConsumedCapacity(value) {
        this.params.ReturnConsumedCapacity = value;
    }
    returnItemCollectionMetrics(value) {
        this.params.ReturnItemCollectionMetrics = value;
    }
    delete(items) {
        if (this.params.RequestItems[this.tableName].length + items.length > MAX_BATCH_WRITE_ITEMS) {
            throw new Error(`batch write takes at max ${MAX_BATCH_WRITE_ITEMS} items`);
        }
        this.params.RequestItems[this.tableName].push(...items.map(this.createDeleteRequest));
        return this;
    }
    put(items) {
        if (this.params.RequestItems[this.tableName].length + items.length > MAX_BATCH_WRITE_ITEMS) {
            throw new Error(`batch write takes at max ${MAX_BATCH_WRITE_ITEMS} items`);
        }
        this.params.RequestItems[this.tableName].push(...items.map(this.createPutRequest));
        return this;
    }
    /**
     *
     * @param backoffTimer generator for how much timeSlots should be waited before requesting next batch. only used when capacity was exceeded. default randomExponentialBackoffTimer
     * @param throttleTimeSlot defines how long one timeSlot is for throttling, default 1 second
     */
    exec(backoffTimer = helper_1.randomExponentialBackoffTimer, throttleTimeSlot = DEFAULT_TIME_SLOT) {
        this.logger.debug('starting batchWriteItem');
        return this.write(backoffTimer, throttleTimeSlot).pipe(operators_1.map(() => {
            return;
        }));
    }
    execFullResponse(backoffTimer = helper_1.randomExponentialBackoffTimer, throttleTimeSlot = DEFAULT_TIME_SLOT) {
        return this.write(backoffTimer, throttleTimeSlot);
    }
    write(backoffTimer, throttleTimeSlot) {
        return batch_write_utils_1.batchWriteItemsWriteAll(this.dynamoRx, Object.assign({}, this.params), backoffTimer(), throttleTimeSlot);
    }
}
exports.BatchWriteSingleTableRequest = BatchWriteSingleTableRequest;
//# sourceMappingURL=batch-write-single-table.request.js.map