import fs from 'fs';
import { TemplateCreator } from './template-creator';
export function keepCase(item) {
    if (typeof item === 'object') {
        if (Array.isArray(item)) {
            return item.map(keepCase);
        }
        if (!Object.prototype.hasOwnProperty.call(item, 'Ref'))
            return Object.keys(item).reduce((prev, next) => ({ ...prev, [next]: keepCase(item[next]) }), { _nocaps: true });
    }
    return item;
}
export function and(a, b) {
    return { "Fn::And": [a, b] };
}
export function or(a, b) {
    return { "Fn::Or": [a, b] };
}
export function equals(a, b) {
    return { "Fn::Equals": [a, b] };
}
export function not(a) {
    return { "Fn::Not": [a] };
}
export function ifCondition(predicate, whenTrue, whenFalse) {
    return { "Fn::If": [predicate, whenTrue, whenFalse] };
}
export class TemplateBuilder {
    aws;
    outputFileName;
    parameterFileName;
    parameters = {};
    outputDir = '';
    conditions = {};
    _templateTransform = template => JSON.stringify(template, null, 2);
    transforms = [];
    constructor(aws, outputFileName, parameterFileName = "parameters.json") {
        this.aws = aws;
        this.outputFileName = outputFileName;
        this.parameterFileName = parameterFileName;
    }
    withCondition(name, predicate) {
        this.conditions[name] = predicate({
            compare: { and, or, equals, not, if: ifCondition },
            params: Object.keys(this.parameters).reduce((prev, parameter) => ({ ...prev, [parameter]: () => ({ 'Ref': parameter }) }), {}),
            condition: (name) => ({ Condition: name })
        });
        return this;
    }
    withTransform(transform) {
        this.transforms.push(transform);
        return this;
    }
    params(params) {
        this.parameters = { ...this.parameters, ...params };
        return this;
    }
    envParams(params) {
        this.parameters = { ...this.parameters, ...Object.keys(params).reduce((prev, key) => ({ ...prev, [key]: { type: 'Future', environmentName: params[key] } }), {}) };
        return this;
    }
    outputTo(directory) {
        this.outputDir = directory;
        return this;
    }
    transformTemplate(_templateTransform = template => JSON.stringify(template, null, 2)) {
        this._templateTransform = _templateTransform;
        return this;
    }
    pathTo(file) {
        if (this.outputDir) {
            fs.mkdirSync(this.outputDir, { recursive: true });
        }
        return (this.outputDir ? this.outputDir + '/' : '') + file;
    }
    build(builder) {
        return TemplateCreator.createWithParams(this.aws, (this.parameters ?? {}), this.conditions, builder, this.pathTo(this.outputFileName), this.pathTo(this.parameterFileName), this._templateTransform, this.transforms.length > 0 ? this.transforms : undefined);
    }
    static create(aws, outputFileName = 'template.json', parametersFileName = 'parameters.json') {
        return new TemplateBuilder(aws, outputFileName, parametersFileName);
    }
}
