"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateDotenvFilename = exports.toDotenvFormat = exports.hydrateEnvs = exports.configToEnv = exports.convertKey = exports.hydrateConfigs = exports.getProjectInfos = void 0;
const clc = require("colorette");
const env = require("./env");
const functionsConfig = require("../functionsConfig");
const error_1 = require("../error");
const logger_1 = require("../logger");
const projectUtils_1 = require("../projectUtils");
const rc_1 = require("../rc");
const utils_1 = require("../utils");
const functional_1 = require("../functional");
function getProjectInfos(options) {
    const result = {};
    const rc = (0, rc_1.loadRC)(options);
    if (rc.projects) {
        for (const [alias, projectId] of Object.entries(rc.projects)) {
            if (Object.keys(result).includes(projectId)) {
                (0, utils_1.logWarning)(`Multiple aliases found for ${clc.bold(projectId)}. ` +
                    `Preferring alias (${clc.bold(result[projectId])}) over (${clc.bold(alias)}).`);
                continue;
            }
            result[projectId] = alias;
        }
    }
    const projectId = (0, projectUtils_1.getProjectId)(options);
    if (projectId && !Object.keys(result).includes(projectId)) {
        result[projectId] = projectId;
    }
    return Object.entries(result).map(([k, v]) => {
        const result = { projectId: k };
        if (k !== v) {
            result.alias = v;
        }
        return result;
    });
}
exports.getProjectInfos = getProjectInfos;
async function hydrateConfigs(pInfos) {
    const hydrate = pInfos.map((info) => {
        return functionsConfig
            .materializeAll(info.projectId)
            .then((config) => {
            info.config = config;
            return;
        })
            .catch((err) => {
            logger_1.logger.debug(`Failed to fetch runtime config for project ${info.projectId}: ${err.message}`);
        });
    });
    await Promise.all(hydrate);
}
exports.hydrateConfigs = hydrateConfigs;
function convertKey(configKey, prefix) {
    const baseKey = configKey
        .toUpperCase()
        .replace(/\./g, "_")
        .replace(/-/g, "_");
    let envKey = baseKey;
    try {
        env.validateKey(envKey);
    }
    catch (err) {
        if (err instanceof env.KeyValidationError) {
            envKey = prefix + envKey;
            env.validateKey(envKey);
        }
    }
    return envKey;
}
exports.convertKey = convertKey;
function configToEnv(configs, prefix) {
    const success = [];
    const errors = [];
    for (const [configKey, value] of (0, functional_1.flatten)(configs)) {
        try {
            const envKey = convertKey(configKey, prefix);
            success.push({ origKey: configKey, newKey: envKey, value: value });
        }
        catch (err) {
            if (err instanceof env.KeyValidationError) {
                errors.push({
                    origKey: configKey,
                    newKey: err.key,
                    err: err.message,
                    value: value,
                });
            }
            else {
                throw new error_1.FirebaseError("Unexpected error while converting config", {
                    exit: 2,
                    original: err,
                });
            }
        }
    }
    return { success, errors };
}
exports.configToEnv = configToEnv;
function hydrateEnvs(pInfos, prefix) {
    let errMsg = "";
    for (const pInfo of pInfos) {
        const { success, errors } = configToEnv(pInfo.config, prefix);
        if (errors.length > 0) {
            const msg = `${pInfo.projectId} ` +
                `${pInfo.alias ? "(" + pInfo.alias + ")" : ""}:\n` +
                errors.map((err) => `\t${err.origKey} => ${clc.bold(err.newKey)} (${err.err})`).join("\n") +
                "\n";
            errMsg += msg;
        }
        else {
            pInfo.envs = success;
        }
    }
    return errMsg;
}
exports.hydrateEnvs = hydrateEnvs;
const CHARACTERS_TO_ESCAPE_SEQUENCES = {
    "\n": "\\n",
    "\r": "\\r",
    "\t": "\\t",
    "\v": "\\v",
    "\\": "\\\\",
    '"': '\\"',
    "'": "\\'",
};
function escape(s) {
    return s.replace(/[\n\r\t\v\\"']/g, (ch) => CHARACTERS_TO_ESCAPE_SEQUENCES[ch]);
}
function toDotenvFormat(envs, header = "") {
    const lines = envs.map(({ newKey, value }) => `${newKey}="${escape(value)}"`);
    const maxLineLen = Math.max(...lines.map((l) => l.length));
    return (`${header}\n` +
        lines.map((line, idx) => `${line.padEnd(maxLineLen)} # from ${envs[idx].origKey}`).join("\n"));
}
exports.toDotenvFormat = toDotenvFormat;
function generateDotenvFilename(pInfo) {
    var _a;
    return `.env.${(_a = pInfo.alias) !== null && _a !== void 0 ? _a : pInfo.projectId}`;
}
exports.generateDotenvFilename = generateDotenvFilename;
