"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HotBuilder = void 0;
const ppath = __importStar(require("path"));
const glob_1 = require("glob");
const HotIO_1 = require("./HotIO");
const HotStaq_1 = require("./HotStaq");
/**
 * Builds stuff for the CLI like docker images and Kubernetes Helm charts.
 */
class HotBuilder {
    constructor(logger) {
        this.interfaces = false;
        this.api = false;
        this.hotstaqVersion = "";
        this.dockerNamespace = "ourfreelight";
        this.dockerFiles = false;
        this.appendReadMe = true;
        this.helmChart = false;
        this.hotsites = [];
        this.logger = logger;
        this.interfaceConfig = {
            filesToGenerate: [],
            tsconfigPath: "",
            outputDir: "./json/"
        };
        this.outputDir = ppath.normalize(`${process.cwd()}/`);
    }
    /**
     * Install a NPM module that utilizes HotStaq.
     */
    static installModule(options) {
        return __awaiter(this, void 0, void 0, function* () {
            let name = options.name;
            let installType = options.installType;
            let processor = options.processor;
            let cwd = options.cwd;
            let hotsite = options.hotsite;
            let hotsitePath = options.hotsitePath;
            let outDir = options.outDir;
            let baseUrl = options.baseUrl;
            if (installType == null)
                installType = "install";
            if (cwd == null)
                cwd = process.cwd();
            let atCount = (name.match(/@/g) || []).length;
            let version = "latest";
            if (atCount > 1) {
                let lastAtIndex = name.lastIndexOf("@");
                version = name.slice(lastAtIndex + 1);
                name = name.substring(0, lastAtIndex);
            }
            if (outDir === "")
                outDir = `${cwd}/public/hotstaq_modules/${name}/`;
            if (baseUrl === "")
                baseUrl = `./hotstaq_modules/${name}/`;
            if ((yield HotIO_1.HotIO.exists(outDir)) === false)
                yield HotIO_1.HotIO.mkdir(outDir);
            let appendVersionStr = "";
            if (installType === "install")
                appendVersionStr = `@${version}`;
            processor.logger.info(`Installing Node Module ${name}${appendVersionStr}`);
            yield HotIO_1.HotIO.exec(`cd ${cwd} && npm ${installType} "${name}${appendVersionStr}"`);
            const pkgObjStr = yield HotIO_1.HotIO.exec(`cd ${cwd} && npm ls --json --depth=0 ${name}`);
            const pkgObj = JSON.parse(pkgObjStr);
            version = `^${pkgObj.dependencies[name].version}`; /// @todo Check on this. Is this ok to do?
            hotsite.dependencies["web"][name] = version;
            yield processor.saveHotSite(hotsitePath);
            let moduleHotsite = options.moduleHotsite;
            if (moduleHotsite.toLowerCase().indexOf(".json") < 0)
                moduleHotsite += ".json";
            moduleHotsite = ppath.normalize(moduleHotsite);
            if ((yield HotIO_1.HotIO.exists(moduleHotsite)) === false) {
                moduleHotsite = options.moduleHotsite;
                if (moduleHotsite.toLowerCase().indexOf(".yaml") < 0)
                    moduleHotsite += ".yaml";
                moduleHotsite = ppath.normalize(moduleHotsite);
            }
            let tempProcessor = new HotStaq_1.HotStaq();
            yield tempProcessor.loadHotSite(moduleHotsite);
            yield tempProcessor.processHotSite();
            let moduleHotsiteJSON = tempProcessor.hotSite;
            let deps = moduleHotsiteJSON.dependencies;
            if (deps != null) {
                if (deps.web != null) {
                    let installs = "";
                    for (let depName in deps.web) {
                        let depVersion = deps.web[depName];
                        installs += `"${depName}@${depVersion}" `;
                    }
                    processor.logger.verbose(`NPM installing ${installs}`);
                    yield HotIO_1.HotIO.exec(`cd ${cwd} && npm install ${installs}`);
                    // Relink anything that needs to be linked.
                    if (installType === "link")
                        yield HotIO_1.HotIO.exec(`cd ${cwd} && npm ${installType} "${name}${appendVersionStr}"`);
                    processor.logger.verbose(`NPM Finished installed`);
                }
            }
            processor.logger.info(`Finished installing Node Module ${name}${appendVersionStr}`);
        });
    }
    /**
     * Build a NPM module that utilizes HotStaq.
     */
    static buildModule(options) {
        return __awaiter(this, void 0, void 0, function* () {
            let name = options.name;
            let buildType = options.buildType;
            let processor = options.processor;
            let cwd = options.cwd;
            let outDir = options.outDir;
            let baseUrl = options.baseUrl;
            let atCount = (name.match(/@/g) || []).length;
            let version = "latest";
            if (atCount > 1) {
                let lastAtIndex = name.lastIndexOf("@");
                version = name.slice(lastAtIndex + 1);
                name = name.substring(0, lastAtIndex);
            }
            let modulePath = options.modulePath;
            let moduleHotsite = options.moduleHotsite;
            if (moduleHotsite.toLowerCase().indexOf(".json") < 0)
                moduleHotsite += ".json";
            moduleHotsite = ppath.normalize(moduleHotsite);
            if ((yield HotIO_1.HotIO.exists(moduleHotsite)) === false) {
                moduleHotsite = options.moduleHotsite;
                if (moduleHotsite.toLowerCase().indexOf(".yaml") < 0)
                    moduleHotsite += ".yaml";
                moduleHotsite = ppath.normalize(moduleHotsite);
            }
            let tempProcessor = new HotStaq_1.HotStaq();
            yield tempProcessor.loadHotSite(moduleHotsite);
            yield tempProcessor.processHotSite();
            let moduleHotsiteJSON = tempProcessor.hotSite;
            let deps = moduleHotsiteJSON.dependencies;
            if (outDir === "")
                outDir = `${cwd}/public/hotstaq_modules/${name}/`;
            if (baseUrl === "")
                baseUrl = `./hotstaq_modules/${name}/`;
            if ((yield HotIO_1.HotIO.exists(outDir)) === false)
                yield HotIO_1.HotIO.mkdir(outDir);
            processor.logger.info(`Building HotStaq Module ${name}`);
            let componentLibrary = "";
            let files = {
                js: [],
                css: [],
                html: [],
                components: []
            };
            if (deps != null) {
                if (deps.webExport != null) {
                    let webExportAbsPath = ppath.normalize(`${modulePath}/${deps.webExport}`);
                    processor.logger.verbose(`Accessing webExport module at ${webExportAbsPath}`);
                    let webExportPath = require.resolve(webExportAbsPath);
                    let webExport = require(webExportPath);
                    if (webExport.buildAssets == null)
                        throw new Error(`The webExport module ${webExportPath} does not have an exported buildAssets function.`);
                    let assetsToCopyObj = yield webExport.buildAssets();
                    processor.logger.verbose(() => `Executed buildAssets. Importing assets ${JSON.stringify(assetsToCopyObj)}`);
                    if (assetsToCopyObj != null) {
                        if (assetsToCopyObj.import != null) {
                            processor.logger.verbose(`Importing assets`);
                            // Copy all files being imported from other NPM modules to the outDir.
                            for (let iIdx = 0; iIdx < assetsToCopyObj.import.length; iIdx++) {
                                let importInfo = assetsToCopyObj.import[iIdx];
                                let importName = "";
                                let importFiles = [];
                                if (typeof (importInfo) === "string")
                                    importName = importInfo;
                                else {
                                    importName = importInfo.name;
                                    importFiles = importInfo.files;
                                }
                                let modulePath = `${cwd}/node_modules/${importName}/`;
                                let fileExts = importFiles;
                                if (importFiles.length === 0)
                                    fileExts = [".min.js", ".umd.js", ".js"];
                                // The order to search for the file extensions and their location is 
                                // crtical. The search will be done in sequential order. This will 
                                // copy Javascript files first, prefering the minified versions.
                                yield HotBuilder.copyFilesFromImport(processor, "js", modulePath, `${outDir}/public/js/`, fileExts, [`${modulePath}/dist/`,
                                    `${modulePath}/dist/js/`,
                                    `${modulePath}/dist/umd/`,
                                    `${modulePath}/build/`,
                                    `${modulePath}/build/js/`,
                                    `${modulePath}/build/umd/`,
                                    `${modulePath}/js/`], files.js, `${baseUrl}/public/js/`, false);
                                if (importFiles.length === 0)
                                    fileExts = [".min.css", ".css"];
                                // Copy the CSS files next, prefering the minified versions.
                                yield HotBuilder.copyFilesFromImport(processor, "css", modulePath, `${outDir}/public/css/`, fileExts, [`${modulePath}/dist/`,
                                    `${modulePath}/dist/css/`,
                                    `${modulePath}/build/`,
                                    `${modulePath}/build/css/`,
                                    `${modulePath}/css/`], files.css, `${baseUrl}/public/css/`, false);
                            }
                            processor.logger.verbose(`Finished importing assets`);
                        }
                        let copyFilesFromAssets = (assets, finalOutDir, finalBaseUrl, outFiles) => __awaiter(this, void 0, void 0, function* () {
                            if ((yield HotIO_1.HotIO.exists(finalOutDir)) === false)
                                yield HotIO_1.HotIO.mkdir(finalOutDir);
                            for (let iIdx = 0; iIdx < assets.length; iIdx++) {
                                let assetObj = assets[iIdx];
                                if (assetObj == null)
                                    continue;
                                let assetPath = "";
                                if (typeof (assetObj) !== "string")
                                    assetPath = assetObj.path;
                                else
                                    assetPath = assetObj;
                                if (modulePath.endsWith("/") === false)
                                    modulePath += "/";
                                assetPath = ppath.normalize(`${modulePath}${assetPath}`);
                                processor.logger.verbose(`Copying files at ${assetPath}`);
                                const files = yield (0, glob_1.glob)(assetPath);
                                for (let iJdx = 0; iJdx < files.length; iJdx++) {
                                    let file = files[iJdx];
                                    let filename = ppath.basename(files[iJdx]);
                                    let src = file;
                                    let dest = ppath.normalize(`${finalOutDir}/${filename}`);
                                    processor.logger.verbose(`Copying file ${src} ${dest}`);
                                    yield HotIO_1.HotIO.copyFile(src, dest);
                                    let webDest = ppath.normalize(`${finalBaseUrl}/${filename}`);
                                    outFiles.push(webDest);
                                }
                            }
                        });
                        if (assetsToCopyObj.html != null)
                            yield copyFilesFromAssets(assetsToCopyObj.html, `${outDir}/public/html/`, `${baseUrl}/public/html/`, files.html);
                        if (assetsToCopyObj.css != null)
                            yield copyFilesFromAssets(assetsToCopyObj.css, `${outDir}/public/css/`, `${baseUrl}/public/css/`, files.css);
                        if (assetsToCopyObj.js != null)
                            yield copyFilesFromAssets(assetsToCopyObj.js, `${outDir}/public/js/`, `${baseUrl}/public/js/`, files.js);
                        if (assetsToCopyObj.componentLibrary != null)
                            componentLibrary = assetsToCopyObj.componentLibrary;
                        if (assetsToCopyObj.components != null) {
                            for (let iIdx = 0; iIdx < assetsToCopyObj.components.length; iIdx++) {
                                // @ts-ignore
                                files.components.push(assetsToCopyObj.components[iIdx]);
                            }
                        }
                    }
                }
            }
            let getFileStr = (outFiles, isAsset = false) => {
                let outputFilesStr = "";
                for (let iIdx = 0; iIdx < outFiles.length; iIdx++) {
                    let file = outFiles[iIdx];
                    let baseFilename = ppath.basename(file);
                    if (isAsset === true) {
                        // Make sure that names are autogenerated as lowercase.
                        const lowerFullname = `${name}/${baseFilename}`.toLowerCase();
                        outputFilesStr += `{ name: "${lowerFullname}", path: "${file}" }, \n`;
                    }
                    else
                        outputFilesStr += `"${file}", \n`;
                }
                if (outputFilesStr !== "")
                    outputFilesStr = outputFilesStr.substr(0, outputFilesStr.length - 3);
                return (outputFilesStr);
            };
            let jsFilesStr = getFileStr(files.js);
            let cssFilesStr = getFileStr(files.css);
            let htmlFilesStr = getFileStr(files.html, true);
            let componentsFilesStr = "";
            for (let iIdx = 0; iIdx < files.components.length; iIdx++) {
                let component = files.components[iIdx];
                componentsFilesStr += `"${component}", \n`;
            }
            if (componentsFilesStr !== "")
                componentsFilesStr = componentsFilesStr.substr(0, componentsFilesStr.length - 3);
            const indexJSPath = ppath.normalize(`${outDir}/index.js`);
            processor.logger.verbose(`Creating index.js file at ${indexJSPath}`);
            yield HotIO_1.HotIO.writeTextFile(indexJSPath, `// Auto-generated by HotStaq ${HotStaq_1.HotStaq.version} on ${new Date().toString()}
let newModule = new HotStaqWeb.HotModule ("${name}");

newModule.js = [${jsFilesStr}];
newModule.css = [${cssFilesStr}];
newModule.html = [${htmlFilesStr}];
newModule.componentLibrary = "${componentLibrary}";
newModule.components = [${componentsFilesStr}];

return (newModule);
`);
            processor.logger.verbose(`Created index.js file`);
            processor.logger.info(`Finished building HotStaq Module ${name}`);
        });
    }
    /**
     * Get the correct NPM name from the given name. This will remove the version.
     */
    static getNameFromNPMName(name) {
        let atCount = (name.match(/@/g) || []).length;
        let version = "latest";
        if (atCount > 1) {
            let lastAtIndex = name.lastIndexOf("@");
            version = name.slice(lastAtIndex + 1);
            name = name.substring(0, lastAtIndex);
        }
        return (name);
    }
    /**
     * Prepare a HotSite for building. This will return the replace keys to use for
     * every file that will be generated. Additionally, this will ensure the HotSite
     * is named properly, and check if the target output directory already exists.
     * Also, this will normalize the output directory.
     *
     * @param generatorType The type of generator to use. Can be:
     * * docker
     * * helm
     */
    prepareHotsiteBuild(hotsite, generatorType) {
        return __awaiter(this, void 0, void 0, function* () {
            if (hotsite.name == null)
                throw new Error(`HotSite ${hotsite.hotsitePath} is missing a name!`);
            HotStaq_1.HotStaq.checkHotSiteName(hotsite.name, true);
            this.outputDir = ppath.normalize(`${this.outputDir}/`);
            let dockerfilePortsStr = "";
            let httpPort = HotStaq_1.HotStaq.getValueFromHotSiteObj(hotsite, ["server", "ports", "http"]);
            let httpsPort = HotStaq_1.HotStaq.getValueFromHotSiteObj(hotsite, ["server", "ports", "https"]);
            let httpApiPort = HotStaq_1.HotStaq.getValueFromHotSiteObj(hotsite, ["server", "ports", "apiHttp"]);
            let httpsApiPort = HotStaq_1.HotStaq.getValueFromHotSiteObj(hotsite, ["server", "ports", "apiHttps"]);
            let hotsitePath = `/app/HotSite.json`;
            if ((yield HotIO_1.HotIO.exists(`${this.outputDir}/${generatorType}/${hotsite.name}/app/`)) === true) {
                this.logger.info(`Unable to create ${generatorType} files because the directory "${this.outputDir}/${generatorType}/${hotsite.name}/app/" already exists!`);
                return;
            }
            yield HotIO_1.HotIO.mkdir(`${this.outputDir}/${generatorType}/${hotsite.name}/app/`);
            if (httpPort != null) {
                dockerfilePortsStr += `ARG HTTP_PORT=${httpPort}
	ENV HTTP_PORT=\${HTTP_PORT}
	EXPOSE \${HTTP_PORT}`;
            }
            if (httpsPort != null) {
                dockerfilePortsStr += `ARG HTTPS_PORT=${httpsPort}
	ENV HTTPS_PORT=\${HTTPS_PORT}
	EXPOSE \${HTTPS_PORT}`;
            }
            if (dockerfilePortsStr === "") {
                httpPort = 5000;
                dockerfilePortsStr += `ARG HTTP_PORT=5000
	ENV HTTP_PORT=\${HTTP_PORT}
	EXPOSE \${HTTP_PORT}`;
            }
            if (httpApiPort == null)
                httpApiPort = 5001;
            let replaceKeys = {
                NAMESPACE: this.dockerNamespace,
                HOTSITE_NAME: hotsite.name,
                REAL_HOTSTAQ_VERSION: this.hotstaqVersion,
                DOCKERFILE_PORTS: dockerfilePortsStr,
                REAL_HTTP_PORT: httpPort.toString(),
                REAL_API_HTTP_PORT: httpApiPort.toString(),
                HOTSITE_PATH: hotsitePath
            };
            return (replaceKeys);
        });
    }
    /**
     * During install, copy files to their correct locations. All copying will
     * stop if stopAfterFirstIsFound is set to true, and the first file is found.
     *
     * @param type The type of file to copy (e.g. "js", "css")
     */
    static copyFilesFromImport(processor_1, type_1, modulePath_1, outDir_1, fileExts_1, searchDirs_1, outFiles_1, baseUrl_1) {
        return __awaiter(this, arguments, void 0, function* (processor, type, modulePath, outDir, fileExts, searchDirs, outFiles, baseUrl, stopAfterFirstIsFound = true) {
            let copyFile = (src, dest, webdest) => __awaiter(this, void 0, void 0, function* () {
                processor.logger.verbose(`Copying file ${src} ${dest}`);
                yield HotIO_1.HotIO.copyFile(src, dest);
                let webDest = webdest;
                outFiles.push(webDest);
            });
            let findAndCopyFile = (path) => __awaiter(this, void 0, void 0, function* () {
                if ((yield HotIO_1.HotIO.exists(path)) === false)
                    return (false);
                for (let iJdx = 0; iJdx < fileExts.length; iJdx++) {
                    let fileExt = fileExts[iJdx];
                    let foundPreferredExt = false;
                    const files = yield (0, glob_1.glob)(`${path}/*${fileExt}`);
                    for (let iIdx = 0; iIdx < files.length; iIdx++) {
                        let file = files[iIdx].toLowerCase();
                        let filename = ppath.basename(files[iIdx]);
                        let findFileExt = ppath.extname(file);
                        if (findFileExt === "")
                            continue;
                        let src = ppath.normalize(`${path}/${filename}`);
                        let dest = ppath.normalize(`${outDir}/${filename}`);
                        let webdest = ppath.normalize(`${baseUrl}/${filename}`);
                        yield copyFile(src, dest, webdest);
                    }
                    foundPreferredExt = true;
                    /// @ts-ignore
                    if (foundPreferredExt === true) {
                        if (stopAfterFirstIsFound === true)
                            return (true);
                        break;
                    }
                }
                return (false);
            });
            if ((yield HotIO_1.HotIO.exists(outDir)) === false)
                yield HotIO_1.HotIO.mkdir(outDir);
            if ((yield HotIO_1.HotIO.exists(`${modulePath}/package.json`)) === true) {
                let packageJSONStr = yield HotIO_1.HotIO.readTextFile(`${modulePath}/package.json`);
                let packageJSONObj = JSON.parse(packageJSONStr);
                let checkProperties = [];
                if (type === "js")
                    checkProperties = ["jsdelivr", "unpkg"];
                if (type === "css")
                    checkProperties = ["style"];
                for (let iIdx = 0; iIdx < checkProperties.length; iIdx++) {
                    let prop = checkProperties[iIdx];
                    if (packageJSONObj[prop] != null) {
                        let filePath = packageJSONObj[prop];
                        let fullFilePath = ppath.normalize(`${modulePath}/${filePath}`);
                        let filename = ppath.basename(fullFilePath);
                        let ext = ppath.extname(filename);
                        let dest = ppath.normalize(`${outDir}/${filename}`);
                        let webdest = ppath.normalize(`${baseUrl}/${filename}`);
                        // Check if the .min version exists
                        if (ext.indexOf(".min.") < 0) {
                            let base = ppath.basename(filename, ext);
                            let tempFilename = `${base}.min${ext}`;
                            let tempDirPath = ppath.dirname(fullFilePath);
                            let tempFullFilePath = ppath.normalize(`${tempDirPath}/${tempFilename}`);
                            if ((yield HotIO_1.HotIO.exists(tempFullFilePath)) === true) {
                                fullFilePath = tempFullFilePath;
                                dest = ppath.normalize(`${outDir}/${tempFilename}`);
                                webdest = ppath.normalize(`${baseUrl}/${tempFilename}`);
                            }
                        }
                        yield copyFile(fullFilePath, dest, webdest);
                        return;
                    }
                }
            }
            for (let iIdx = 0; iIdx < searchDirs.length; iIdx++) {
                let searchDir = ppath.normalize(searchDirs[iIdx]);
                const copiedFile = yield findAndCopyFile(searchDir);
                if (copiedFile === true)
                    return;
            }
        });
    }
    /**
     * Build everything and output to outputDir.
     *
     * @fixme Needs tests!
     */
    build() {
        return __awaiter(this, void 0, void 0, function* () {
            let hotPackageJSONStr = yield HotIO_1.HotIO.readTextFile(ppath.normalize(`${__dirname}/../../package.json`));
            let hotPackageJSONObj = JSON.parse(hotPackageJSONStr);
            if (this.hotstaqVersion === "")
                this.hotstaqVersion = hotPackageJSONObj.version;
            this.logger.info(`Generating using HotStaq version: ${this.hotstaqVersion}`);
            if (this.interfaces === true) {
                if (this.interfaceConfig.tsconfigPath === "")
                    this.interfaceConfig.tsconfigPath = ppath.normalize(`${process.cwd()}/tsconfig.json`);
                if (this.interfaceConfig.outputDir === "")
                    throw new Error(`The output directory for the interface generation is not set!`);
                this.logger.info(`Generating IHotParameter objects to: ${this.interfaceConfig.outputDir}`);
                this.logger.info(`Using tsconfig: ${this.interfaceConfig.tsconfigPath}`);
                if ((yield HotIO_1.HotIO.exists(this.interfaceConfig.outputDir)) === false)
                    yield HotIO_1.HotIO.mkdir(this.interfaceConfig.outputDir);
                for (let iIdx = 0; iIdx < this.hotsites.length; iIdx++) {
                    const hotsite = this.hotsites[iIdx];
                    if (hotsite.server != null) {
                        if (hotsite.server.interfaces != null) {
                            if (hotsite.server.interfaces.generate != null) {
                                this.logger.info(`Collecting list of interfaces from HotSite ${hotsite.name}...`);
                                for (let iJdx = 0; iJdx < hotsite.server.interfaces.generate.length; iJdx++) {
                                    const interfaceGenObj = hotsite.server.interfaces.generate[iJdx];
                                    let interfaceGen = {
                                        name: interfaceGenObj
                                    };
                                    if (typeof (interfaceGenObj) !== "string")
                                        interfaceGen = interfaceGenObj;
                                    // @ts-ignore
                                    this.interfaceConfig.filesToGenerate.push(interfaceGen);
                                }
                            }
                        }
                    }
                }
                if (this.interfaceConfig.filesToGenerate.length === 0) {
                    this.logger.info(`No files to generate!`);
                    return;
                }
                for (let iIdx = 0; iIdx < this.interfaceConfig.filesToGenerate.length; iIdx++) {
                    const interfaceGen = this.interfaceConfig.filesToGenerate[iIdx];
                    // @ts-ignore
                    const ifaceName = (typeof (interfaceGen) === "string") ? interfaceGen : interfaceGen.name;
                    this.logger.info(`Generating IHotParameter objects for ${ifaceName}...`);
                    const params = yield HotStaq_1.HotStaq.convertInterfaceToRouteParameters(ifaceName, false, { "tsconfigPath": this.interfaceConfig.tsconfigPath });
                    const finalPath = ppath.normalize(`${this.interfaceConfig.outputDir}/${ifaceName}.json`);
                    yield HotIO_1.HotIO.writeTextFile(finalPath, JSON.stringify(params, null, 2));
                    this.logger.info(`Wrote to: ${finalPath}`);
                }
                this.logger.info(`Finished generating objects!`);
            }
            if (this.api === true)
                throw new Error("This is not implemented yet...");
            if (this.dockerFiles === true) {
                this.logger.info("Building docker files...");
                const dockerDir = ppath.normalize(`${__dirname}/../../builder/docker`);
                for (let iIdx = 0; iIdx < this.hotsites.length; iIdx++) {
                    const hotsite = this.hotsites[iIdx];
                    this.logger.info(`Preparing Dockerfile "${hotsite.name}"...`);
                    let replaceKeys = yield this.prepareHotsiteBuild(hotsite, "docker");
                    this.logger.info(`Building Dockerfile "${hotsite.name}"...`);
                    this.logger.info(`Output Directory: ${dockerDir}`);
                    yield HotIO_1.HotIO.copyFile(ppath.normalize(`${dockerDir}/Dockerfile.hardened.linux.gen`), `${this.outputDir}/docker/${hotsite.name}/prod.dockerfile`);
                    yield HotIO_1.HotIO.copyFile(ppath.normalize(`${dockerDir}/Dockerfile.linux.gen`), `${this.outputDir}/docker/${hotsite.name}/dev.dockerfile`);
                    yield this.replaceKeysInFile(`${this.outputDir}/docker/${hotsite.name}/prod.dockerfile`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/docker/${hotsite.name}/dev.dockerfile`, replaceKeys);
                    yield HotIO_1.HotIO.copyFiles(`${dockerDir}/scripts/`, `${this.outputDir}/`);
                    yield HotIO_1.HotIO.copyFiles(`${dockerDir}/app/`, `${this.outputDir}/docker/${hotsite.name}/app/`);
                    yield HotIO_1.HotIO.copyFile(`${dockerDir}/dockerignore`, `${this.outputDir}/.dockerignore`);
                    yield HotIO_1.HotIO.copyFile(`${dockerDir}/docker-compose.gen.yaml`, `${this.outputDir}/docker-compose.yaml`);
                    yield HotIO_1.HotIO.copyFile(`${dockerDir}/env-skeleton`, `${this.outputDir}/env-skeleton`);
                    yield this.replaceKeysInFile(`${this.outputDir}/docker/${hotsite.name}/app/start.sh`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/docker/${hotsite.name}/app/start-pkg.sh`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/env-skeleton`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/docker-compose.yaml`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/build.bat`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/build.sh`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/start.bat`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/start.sh`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/stop.bat`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/stop.sh`, replaceKeys);
                    if ((yield HotIO_1.HotIO.exists(`${this.outputDir}/README.md`)) === true) {
                        const prevREADME = yield HotIO_1.HotIO.readTextFile(`${this.outputDir}/README.md`);
                        const dockerREADME = yield HotIO_1.HotIO.readTextFile(`${dockerDir}/README.md`);
                        // Only append the docker readme if it's not already there...
                        if (prevREADME.indexOf("Docker Getting Started") < 0)
                            yield HotIO_1.HotIO.writeTextFile(`${this.outputDir}/README.md`, `${prevREADME}\n${dockerREADME}`);
                    }
                    this.logger.info(`Finished building Dockerfile "${hotsite.name}"...`);
                }
                this.logger.info("Finished building docker files...");
            }
            if (this.helmChart === true) {
                this.logger.info("Building helm chart files (THIS IS EXPERIMENTAL AND UNTESTED)...");
                const helmDir = ppath.normalize(`${__dirname}/../../builder/helm-chart`);
                this.logger.info(`Output Directory: ${helmDir}`);
                for (let iIdx = 0; iIdx < this.hotsites.length; iIdx++) {
                    const hotsite = this.hotsites[iIdx];
                    this.logger.info(`Preparing Helm Chart "${hotsite.name}"...`);
                    let replaceKeys = yield this.prepareHotsiteBuild(hotsite, "helm");
                    this.logger.info(`Building Helm Chart "${hotsite.name}"...`);
                    yield HotIO_1.HotIO.copyFiles(`${helmDir}/`, `${this.outputDir}/helm/`);
                    this.logger.info(`Helm Chart ${hotsite.name} Output Directory: ${this.outputDir}/helm/`);
                    yield this.replaceKeysInFile(`${this.outputDir}/helm/values.yaml`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/helm/Chart.yaml`, replaceKeys);
                    yield this.replaceKeysInFile(`${this.outputDir}/helm/README.md`, replaceKeys);
                    this.logger.info("Finished building Helm Chart...");
                }
                this.logger.info("Finished building helm chart files (THIS IS EXPERIMENTAL AND UNTESTED)...");
            }
        });
    }
    /**
     * Replace keys in a file.
     */
    replaceKeysInFile(filepath, keys) {
        return __awaiter(this, void 0, void 0, function* () {
            let contents = yield HotIO_1.HotIO.readTextFile(filepath);
            for (let key in keys) {
                let value = keys[key];
                contents = HotStaq_1.HotStaq.replaceKey(contents, key, value);
            }
            yield HotIO_1.HotIO.writeTextFile(filepath, contents);
        });
    }
}
exports.HotBuilder = HotBuilder;
//# sourceMappingURL=HotBuilder.js.map