import { isObject, isString } from 'lodash';
import { map } from 'rxjs/operators';
import { MetadataHelper } from '../../decorator/metadata/metadata-helper';
import { Mapper } from '../../mapper/mapper';
import { DEFAULT_SESSION_VALIDITY_ENSURER } from '../default-session-validity-ensurer.const';
import { DEFAULT_TABLE_NAME_RESOLVER } from '../default-table-name-resolver.const';
import { DynamoRx } from '../dynamo-rx';
import { REGEX_TABLE_NAME } from '../request/regex';
var BatchGetRequest = /** @class */ (function () {
    function BatchGetRequest(tableNameResolver, sessionValidityEnsurer) {
        if (tableNameResolver === void 0) { tableNameResolver = DEFAULT_TABLE_NAME_RESOLVER; }
        if (sessionValidityEnsurer === void 0) { sessionValidityEnsurer = DEFAULT_SESSION_VALIDITY_ENSURER; }
        this.tableNameResolver = tableNameResolver;
        this.tables = new Map();
        this.dynamoRx = new 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}
     */
    BatchGetRequest.prototype.forModel = function (modelClazz, keys) {
        var 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);
        var metadata = MetadataHelper.get(modelClazz);
        var attributeMaps = [];
        // loop over all the keys
        keys.forEach(function (key) {
            var idOb = {};
            if (isString(key)) {
                // got a simple primary key
                var value = Mapper.toDbOne(key);
                if (value === null) {
                    throw Error('please provide an actual value for partition key');
                }
                // FIXME: should work  without cast - because keyof T must be a string or symbol (error exists since update to  2.9.x -> check in a later version, there are some open issues)
                idOb[metadata.getPartitionKey()] = value;
            }
            else if (isObject(key) && key.partitionKey !== undefined && key.partitionKey !== null) {
                // got a composite primary key
                // partition key
                var mappedPartitionKey = Mapper.toDbOne(key.partitionKey);
                if (mappedPartitionKey === null) {
                    throw Error('please provide an actual value for partition key');
                }
                idOb[metadata.getPartitionKey()] = mappedPartitionKey;
                // sort key
                var mappedSortKey = Mapper.toDbOne(key.sortKey);
                if (mappedSortKey === null) {
                    throw Error('please provide an actual value for partition key');
                }
                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;
    };
    BatchGetRequest.prototype.execFullResponse = function () {
        var _this = this;
        return this.dynamoRx.batchGetItems(this.params).pipe(map(function (response) {
            var r = {
                ConsumedCapacity: response.ConsumedCapacity,
                UnprocessedKeys: response.UnprocessedKeys,
                Responses: {},
            };
            if (response.Responses && Object.keys(response.Responses).length) {
                Object.keys(response.Responses).forEach(function (tableName) {
                    var mapped = response.Responses[tableName].map(function (attributeMap) {
                        return Mapper.fromDb(attributeMap, _this.tables.get(tableName));
                    });
                    r.Responses[tableName] = mapped;
                });
            }
            return r;
        }));
    };
    BatchGetRequest.prototype.exec = function () {
        var _this = this;
        return this.dynamoRx.batchGetItems(this.params).pipe(map(function (response) {
            var r = {};
            if (response.Responses && Object.keys(response.Responses).length) {
                Object.keys(response.Responses).forEach(function (tableName) {
                    var mapped = response.Responses[tableName].map(function (attributeMap) {
                        return Mapper.fromDb(attributeMap, _this.tables.get(tableName));
                    });
                    r[tableName] = mapped;
                });
                return r;
            }
            else {
                return {};
            }
        }));
    };
    BatchGetRequest.prototype.getTableName = function (modelClazz, tableNameResolver) {
        var tableName = tableNameResolver(MetadataHelper.get(modelClazz).modelOptions.tableName);
        if (!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;
    };
    return BatchGetRequest;
}());
export { BatchGetRequest };
//# sourceMappingURL=batch-get.request.js.map