import { Iam, Policy } from "../iam/PolicyDocument";
import { normalize } from "../cloudformation";
import { join } from "../Value";
export function grantTableAccess(role, policyName, tables) {
    const indexes = tables.flatMap(it => (it.properties.globalSecondaryIndexes ?? []).map(gsi => join(it.attributes.Arn, '/index/', gsi.indexName)));
    Iam.from(role).add(policyName, Policy.allow("dynamodb:*", [...tables.map(table => table.attributes.Arn), ...indexes]));
}
export function dynamoTable(aws, definition, name, props) {
    const indexKeys = Object.keys(definition.indexes ?? {}).flatMap(key => [definition.indexes[key].partitionKey, ...(definition.indexes[key].sortKey ? [definition.indexes[key].sortKey] : [])]);
    const keys = [...new Set([definition.partitionKey, ...(definition.sortKey ? [definition.sortKey] : []), ...indexKeys])];
    function typeFor(key) {
        const type = definition.definition[key];
        const nonOptionalType = `${type}`.endsWith('?') ? type.toString().substring(0, type.toString().length - 1) : type;
        switch (nonOptionalType) {
            case 'string':
                return 'S';
            case 'string set':
                return 'SS';
            case 'number':
                return 'N';
            case 'number set':
                return 'NS';
            case 'binary':
                return 'B';
            case 'binary set':
                return 'BS';
            case 'boolean':
                return 'BOOL';
            case 'null':
                return 'NULL';
            case 'list':
                return 'L';
            default:
                return 'M';
        }
    }
    return aws.dynamodb.table({
        ...(name ? { _logicalName: normalize(name) } : {}),
        ...props,
        ...(name ? { tableName: name } : {}),
        keySchema: [{ keyType: 'HASH', attributeName: definition.partitionKey }, ...(definition.sortKey ? [{ keyType: 'RANGE', attributeName: definition.sortKey }] : [])],
        attributeDefinitions: keys.map(key => ({ attributeName: key, attributeType: typeFor(key) })),
        ...((definition.indexes && Object.keys(definition.indexes).length > 0) ? { globalSecondaryIndexes: Object.keys(definition.indexes).map(key => {
                return {
                    indexName: key,
                    keySchema: [{
                            keyType: 'HASH',
                            attributeName: definition.indexes[key].partitionKey
                        }, ...(definition.indexes[key].sortKey ? [{
                                keyType: 'RANGE',
                                attributeName: definition.indexes[key].sortKey
                            }] : [])],
                    projection: { projectionType: 'ALL' }
                };
            }) } : {})
    });
}
