"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const operators_1 = require("rxjs/operators");
const metadata_1 = require("../../decorator/metadata");
const metadata_helper_1 = require("../../decorator/metadata/metadata-helper");
const mapper_1 = require("../../mapper");
const default_session_validity_ensurer_const_1 = require("../default-session-validity-ensurer.const");
const default_table_name_resolver_const_1 = require("../default-table-name-resolver.const");
const dynamo_rx_1 = require("../dynamo-rx");
const regex_1 = require("../request/regex");
class BatchGetRequest {
    constructor(tableNameResolver = default_table_name_resolver_const_1.DEFAULT_TABLE_NAME_RESOLVER, sessionValidityEnsurer = default_session_validity_ensurer_const_1.DEFAULT_SESSION_VALIDITY_ENSURER) {
        this.tableNameResolver = tableNameResolver;
        this.tables = new Map();
        this.dynamoRx = new dynamo_rx_1.DynamoRx(sessionValidityEnsurer);
        this.params = {
            RequestItems: {},
        };
    }
    /**
     * @param {ModelConstructor<T>} modelClazz
     * @param {any[]} keys either a simple string for partition key or an object with partitionKey and sortKey
     * @returns {BatchGetSingleTableRequest}
     */
    forModel(modelClazz, keys) {
        const tableName = this.getTableName(modelClazz, this.tableNameResolver);
        if (this.tables.has(tableName)) {
            throw new Error('table name already exists, please provide all the keys for the same table at once');
        }
        this.tables.set(tableName, modelClazz);
        const metadata = metadata_helper_1.metadataForClass(modelClazz);
        const attributeMaps = [];
        // loop over all the keys
        keys.forEach(key => {
            const idOb = {};
            if (lodash_1.isString(key)) {
                // got a simple primary key
                const value = mapper_1.toDbOne(key);
                if (value === null) {
                    throw Error('please provide an actual value for partition key');
                }
                idOb[metadata.getPartitionKey()] = value;
            }
            else if (lodash_1.isObject(key) && key.partitionKey !== undefined && key.partitionKey !== null) {
                // got a composite primary key
                // partition key
                const mappedPartitionKey = mapper_1.toDbOne(key.partitionKey);
                if (mappedPartitionKey === null) {
                    throw Error('please provide an actual value for partition key');
                }
                idOb[metadata.getPartitionKey()] = mappedPartitionKey;
                // sort key
                const mappedSortKey = mapper_1.toDbOne(key.sortKey);
                if (mappedSortKey === null) {
                    throw Error('please provide an actual value for partition key');
                }
                if (metadata_1.hasSortKey(metadata)) {
                    idOb[metadata.getSortKey()] = mappedSortKey;
                }
            }
            else {
                throw new Error('a key must either be a string or a PrimaryKey');
            }
            attributeMaps.push(idOb);
        });
        this.params.RequestItems[tableName] = {
            Keys: attributeMaps,
        };
        return this;
    }
    execFullResponse() {
        return this.dynamoRx.batchGetItems(this.params).pipe(operators_1.map(response => {
            let Responses = {};
            if (response.Responses && Object.keys(response.Responses).length) {
                Responses = Object.entries(response.Responses).reduce((u, [key, val]) => {
                    u[key] = val.map(attributes => mapper_1.fromDb(attributes, this.tables.get(key)));
                    return u;
                }, {});
            }
            return {
                ConsumedCapacity: response.ConsumedCapacity,
                UnprocessedKeys: response.UnprocessedKeys,
                Responses,
            };
        }));
    }
    exec() {
        return this.dynamoRx.batchGetItems(this.params).pipe(operators_1.map(response => {
            if (response.Responses && Object.keys(response.Responses).length) {
                return Object.entries(response.Responses).reduce((u, [key, val]) => {
                    u[key] = val.map(attributeMap => mapper_1.fromDb(attributeMap, this.tables.get(key)));
                    return u;
                }, {});
            }
            return {};
        }));
    }
    getTableName(modelClazz, tableNameResolver) {
        const tableName = tableNameResolver(metadata_helper_1.metadataForClass(modelClazz).modelOptions.tableName);
        if (!regex_1.REGEX_TABLE_NAME.test(tableName)) {
            throw new Error('make sure the table name only contains these characters «a-z A-Z 0-9 - _ .» and is between 3 and 255 characters long');
        }
        return tableName;
    }
}
exports.BatchGetRequest = BatchGetRequest;
//# sourceMappingURL=batch-get.request.js.map