"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const util_1 = require("../core/util");
const cloudformation_token_1 = require("./cloudformation-token");
const stack_1 = require("./stack");
/**
 * Represents a CloudFormation resource.
 */
class Resource extends stack_1.Referenceable {
    /**
     * Creates a resource construct.
     * @param resourceType The CloudFormation type of this resource (e.g. AWS::DynamoDB::Table)
     */
    constructor(parent, name, props) {
        super(parent, name);
        /**
         * Options for this resource, such as condition, update policy etc.
         */
        this.options = {};
        this.dependsOn = new Array();
        if (!props.type) {
            throw new Error('The `type` property is required');
        }
        this.resourceType = props.type;
        this.properties = props.properties || {};
        // 'name' is a special property included for resource constructs and passed
        // as 'name', but we don't want it to be serialized into the template.
        if (this.properties.name) {
            delete this.properties.name;
        }
    }
    /**
     * A decoration used to create a CloudFormation attribute property.
     * @param customName Custom name for the attribute (default is the name of the property)
     * NOTE: we return "any" here to satistfy jsii, which doesn't support lambdas.
     */
    static attribute(customName) {
        return (prototype, key) => {
            const name = customName || key;
            Object.defineProperty(prototype, key, {
                get() {
                    return this.getAtt(name);
                }
            });
        };
    }
    /**
     * Returns a token for an runtime attribute of this resource.
     * Ideally, use generated attribute accessors (e.g. `resource.arn`), but this can be used for future compatibility
     * in case there is no generated attribute.
     * @param attributeName The name of the attribute.
     */
    getAtt(attributeName) {
        return new cloudformation_token_1.CloudFormationToken({ 'Fn::GetAtt': [this.logicalId, attributeName] }, `${this.logicalId}.${attributeName}`);
    }
    /**
     * Adds a dependency on another resource.
     * @param other The other resource.
     */
    addDependency(...other) {
        this.dependsOn.push(...other);
    }
    /**
     * Emits CloudFormation for this resource.
     */
    toCloudFormation() {
        try {
            return {
                Resources: {
                    [this.logicalId]: {
                        Type: this.resourceType,
                        Properties: util_1.ignoreEmpty(this.renderProperties()),
                        DependsOn: util_1.ignoreEmpty(this.renderDependsOn()),
                        CreationPolicy: util_1.capitalizePropertyNames(this.options.creationPolicy),
                        UpdatePolicy: util_1.capitalizePropertyNames(this.options.updatePolicy),
                        DeletionPolicy: util_1.capitalizePropertyNames(this.options.deletionPolicy),
                        Metadata: util_1.ignoreEmpty(this.options.metadata),
                        Condition: this.options.condition && this.options.condition.logicalId
                    }
                }
            };
        }
        catch (e) {
            // Change message
            e.message = `While synthesizing ${this.path}: ${e.message}`;
            // Adjust stack trace (make it look like node built it, too...)
            const creationStack = ['--- resource created at ---', ...this.creationStackTrace].join('\n    at ');
            const problemTrace = e.stack.substr(e.stack.indexOf(e.message) + e.message.length);
            e.stack = `${e.message}\n    ${creationStack}\n    --- problem discovered at ---${problemTrace}`;
            // Re-throw
            throw e;
        }
    }
    renderProperties() {
        // FIXME: default implementation is not great, it should throw, but it avoids breaking all unit tests for now.
        return this.properties;
    }
    renderDependsOn() {
        const logicalIDs = new Set();
        for (const d of this.dependsOn) {
            addDependency(d);
        }
        return Array.from(logicalIDs);
        function addDependency(d) {
            d.dependencyElements.forEach(dep => {
                const logicalId = dep.logicalId;
                if (logicalId) {
                    logicalIDs.add(logicalId);
                }
            });
            // break if dependencyElements include only 'd', which means we reached a terminal.
            if (d.dependencyElements.length === 1 && d.dependencyElements[0] === d) {
                return;
            }
            else {
                d.dependencyElements.forEach(dep => addDependency(dep));
            }
        }
    }
}
exports.Resource = Resource;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJyZXNvdXJjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLHVDQUFvRTtBQUNwRSxpRUFBNkQ7QUFHN0QsbUNBQW1FO0FBY25FOztHQUVHO0FBQ0gsTUFBYSxRQUFTLFNBQVEscUJBQWE7SUFrQ3ZDOzs7T0FHRztJQUNILFlBQVksTUFBaUIsRUFBRSxJQUFZLEVBQUUsS0FBb0I7UUFDN0QsS0FBSyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQXRCeEI7O1dBRUc7UUFDYSxZQUFPLEdBQW9CLEVBQUUsQ0FBQztRQVl0QyxjQUFTLEdBQUcsSUFBSSxLQUFLLEVBQWUsQ0FBQztRQVN6QyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRTtZQUNiLE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLENBQUMsQ0FBQztTQUN0RDtRQUVELElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQztRQUMvQixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQyxVQUFVLElBQUksRUFBRyxDQUFDO1FBRTFDLDJFQUEyRTtRQUMzRSxzRUFBc0U7UUFDdEUsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRTtZQUN0QixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO1NBQy9CO0lBQ0wsQ0FBQztJQXBERDs7OztPQUlHO0lBQ0ksTUFBTSxDQUFDLFNBQVMsQ0FBQyxVQUFtQjtRQUN2QyxPQUFPLENBQUMsU0FBYyxFQUFFLEdBQVcsRUFBRSxFQUFFO1lBQ25DLE1BQU0sSUFBSSxHQUFHLFVBQVUsSUFBSSxHQUFHLENBQUM7WUFDL0IsTUFBTSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUUsR0FBRyxFQUFFO2dCQUNsQyxHQUFHO29CQUNDLE9BQVEsSUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDdEMsQ0FBQzthQUNK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