import { KEY_MODEL } from '../impl/model/key-model.const';
/**
 * Checks if given metadata returns a sort key when calling metadata.getSortKey
 */
export function hasSortKey(metadata) {
    return metadata.getSortKey() !== null;
}
var Metadata = /** @class */ (function () {
    function Metadata(modelConstructor) {
        this.modelOptions = Reflect.getMetadata(KEY_MODEL, modelConstructor);
    }
    Metadata.prototype.forProperty = function (propertyKey) {
        var options;
        if (this.modelOptions.properties) {
            options = this.modelOptions.properties.find(function (property) { return property.name === propertyKey || property.nameDb === propertyKey; });
        }
        return options;
    };
    /**
     *
     * @returns {Array<PropertyMetadata<any>>} Returns all the properties property the @PartitionKeyUUID decorator is present, returns an empty array by default
     */
    Metadata.prototype.getKeysWithUUID = function () {
        return filterBy(this.modelOptions, function (p) { return !!(p.key && p.key.uuid); }, []);
    };
    /**
     * @param {string} indexName
     * @returns {string} Returns the name of partition key (not the db name if it differs from property name)
     * @throws Throws an error if no partition key was defined for the current model
     * @throws Throws an error if an indexName was delivered but no index was found for given name
     */
    Metadata.prototype.getPartitionKey = function (indexName) {
        if (indexName) {
            var index = this.getIndex(indexName);
            if (index) {
                return index.partitionKey;
            }
            else {
                throw new Error("there is no index defined for name " + indexName);
            }
        }
        else {
            var property = filterByFirst(this.modelOptions, function (p) { return !!(p.key && p.key.type === 'HASH'); });
            if (property) {
                return property.name;
            }
            else {
                throw new Error('could not find any partition key');
            }
        }
    };
    /**
     * @param {string} indexName
     * @returns {keyof T} Returns the name of sort key (not the db name if it differs from property name) or null if none was defined
     * @throws Throws an error if an indexName was delivered but no index was found for given name or the found index has no sort key defined
     */
    Metadata.prototype.getSortKey = function (indexName) {
        if (indexName) {
            var index = this.getIndex(indexName);
            if (index) {
                if (index.sortKey) {
                    return index.sortKey;
                }
                else {
                    throw new Error("there is no sort key defined for index " + indexName);
                }
            }
            else {
                throw new Error("there is no index defined for name " + indexName);
            }
        }
        else {
            var property = filterByFirst(this.modelOptions, function (p) { return !!(p.key && p.key.type === 'RANGE'); });
            return property ? property.name : null;
        }
    };
    /**
     *
     * @returns {SecondaryIndex[]} Returns all the secondary indexes if exists or an empty array if none is defined
     */
    Metadata.prototype.getIndexes = function () {
        if (this.modelOptions.indexes && this.modelOptions.indexes.size) {
            return Array.from(this.modelOptions.indexes.values());
        }
        else {
            return [];
        }
    };
    /**
     * @param {string} indexName
     * @returns {SecondaryIndex} Returns the index if one with given name exists, null otherwise
     */
    Metadata.prototype.getIndex = function (indexName) {
        if (this.modelOptions.indexes) {
            var index = this.modelOptions.indexes.get(indexName);
            return index ? index : null;
        }
        return null;
    };
    return Metadata;
}());
export { Metadata };
function filterBy(modelOptions, predicate, defaultValue) {
    if (modelOptions && modelOptions.properties) {
        var properties = modelOptions.properties.filter(predicate);
        if (properties && properties.length) {
            return properties;
        }
    }
    return defaultValue;
}
function filterByFirst(modelOptions, predicate) {
    var properties = filterBy(modelOptions, predicate, null);
    return properties && properties.length ? properties[0] : null;
}
//# sourceMappingURL=metadata.js.map