"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const aws_s3_notifications_1 = require("@aws-cdk/aws-s3-notifications");
const cdk = require("@aws-cdk/cdk");
const notifications_resource_handler_1 = require("./notifications-resource-handler");
/**
 * A custom CloudFormation resource that updates bucket notifications for a
 * bucket. The reason we need it is because the AWS::S3::Bucket notification
 * configuration is defined on the bucket itself, which makes it impossible to
 * provision notifications at the same time as the target (since
 * PutBucketNotifications validates the targets).
 *
 * Since only a single BucketNotifications resource is allowed for each Bucket,
 * this construct is not exported in the public API of this module. Instead, it
 * is created just-in-time by `s3.Bucket.onEvent`, so a 1:1 relationship is
 * ensured.
 *
 * @see
 * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-notificationconfig.html
 */
class BucketNotifications extends cdk.Construct {
    constructor(parent, id, props) {
        super(parent, id);
        this.lambdaNotifications = new Array();
        this.queueNotifications = new Array();
        this.topicNotifications = new Array();
        this.customResourceCreated = false;
        this.bucket = props.bucket;
    }
    /**
     * Adds a notification subscription for this bucket.
     * If this is the first notification, a BucketNotification resource is added to the stack.
     *
     * @param event The type of event
     * @param target The target construct
     * @param filters A set of S3 key filters
     */
    addNotification(event, target, ...filters) {
        this.createResourceOnce();
        // resolve target. this also provides an opportunity for the target to e.g. update
        // policies to allow this notification to happen.
        const targetProps = target.asBucketNotificationDestination(this.bucket.bucketArn, this.bucket.uniqueId);
        const commonConfig = {
            Events: [event],
            Filter: renderFilters(filters),
        };
        // based on the target type, add the the correct configurations array
        switch (targetProps.type) {
            case aws_s3_notifications_1.BucketNotificationDestinationType.Lambda:
                this.lambdaNotifications.push(Object.assign({}, commonConfig, { LambdaFunctionArn: targetProps.arn }));
                break;
            case aws_s3_notifications_1.BucketNotificationDestinationType.Queue:
                this.queueNotifications.push(Object.assign({}, commonConfig, { QueueArn: targetProps.arn }));
                break;
            case aws_s3_notifications_1.BucketNotificationDestinationType.Topic:
                this.topicNotifications.push(Object.assign({}, commonConfig, { TopicArn: targetProps.arn }));
                break;
            default:
                throw new Error('Unsupported notification target type:' + aws_s3_notifications_1.BucketNotificationDestinationType[targetProps.type]);
        }
    }
    renderNotificationConfiguration() {
        return {
            LambdaFunctionConfigurations: this.lambdaNotifications.length > 0 ? this.lambdaNotifications : undefined,
            QueueConfigurations: this.queueNotifications.length > 0 ? this.queueNotifications : undefined,
            TopicConfigurations: this.topicNotifications.length > 0 ? this.topicNotifications : undefined
        };
    }
    /**
     * Defines the bucket notifications resources in the stack only once.
     * This is called lazily as we add notifications, so that if notifications are not added,
     * there is no notifications resource.
     */
    createResourceOnce() {
        if (this.customResourceCreated) {
            return;
        }
        const handlerArn = notifications_resource_handler_1.NotificationsResourceHandler.singleton(this);
        new cdk.Resource(this, 'Resource', {
            type: 'Custom::S3BucketNotifications',
            properties: {
                ServiceToken: handlerArn,
                BucketName: this.bucket.bucketName,
                NotificationConfiguration: new cdk.Token(() => this.renderNotificationConfiguration())
            }
        });
        this.customResourceCreated = true;
    }
}
exports.BucketNotifications = BucketNotifications;
function renderFilters(filters) {
    if (!filters || filters.length === 0) {
        return undefined;
    }
    const renderedRules = new Array();
    for (const rule of filters) {
        if (!rule.suffix && !rule.prefix) {
            throw new Error('NotificationKeyFilter must specify `prefix` and/or `suffix`');
        }
        if (rule.suffix) {
            renderedRules.push({ Name: 'suffix', Value: rule.suffix });
        }
        if (rule.prefix) {
            renderedRules.push({ Name: 'prefix', Value: rule.prefix });
        }
    }
    return {
        Key: {
            FilterRules: renderedRules
        }
    };
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWZpY2F0aW9ucy1yZXNvdXJjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm5vdGlmaWNhdGlvbnMtcmVzb3VyY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSx3RUFBa0g7QUFDbEgsb0NBQXFDO0FBRXJDLHFGQUFnRjtBQVloRjs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQWEsbUJBQW9CLFNBQVEsR0FBRyxDQUFDLFNBQVM7SUFPbEQsWUFBWSxNQUFxQixFQUFFLEVBQVUsRUFBRSxLQUF5QjtRQUNwRSxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBUEwsd0JBQW1CLEdBQUcsSUFBSSxLQUFLLEVBQStCLENBQUM7UUFDL0QsdUJBQWtCLEdBQUcsSUFBSSxLQUFLLEVBQXNCLENBQUM7UUFDckQsdUJBQWtCLEdBQUcsSUFBSSxLQUFLLEVBQXNCLENBQUM7UUFDOUQsMEJBQXFCLEdBQUcsS0FBSyxDQUFDO1FBS2xDLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUMvQixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNJLGVBQWUsQ0FBQyxLQUFnQixFQUFFLE1BQXNDLEVBQUUsR0FBRyxPQUFnQztRQUNoSCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUUxQixrRkFBa0Y7UUFDbEYsaURBQWlEO1FBQ2pELE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQywrQkFBK0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3hHLE1BQU0sWUFBWSxHQUF3QjtZQUN0QyxNQUFNLEVBQUUsQ0FBRSxLQUFLLENBQUU7WUFDakIsTUFBTSxFQUFFLGFBQWEsQ0FBQyxPQUFPLENBQUM7U0FDakMsQ0FBQztRQUVGLHFFQUFxRTtRQUNyRSxRQUFRLFdBQVcsQ0FBQyxJQUFJLEVBQUU7WUFDdEIsS0FBSyx3REFBaUMs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