"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fullDepthInspectOptions = exports.CONTROL_CHAR_REGEXP_ALLOW_SIMPLE = exports.CONTROL_CHAR_REGEXP = void 0;
exports.formatOutput = formatOutput;
exports.formatError = formatError;
const numeral_1 = __importDefault(require("numeral"));
const text_table_1 = __importDefault(require("text-table"));
const i18n_1 = __importDefault(require("@mongosh/i18n"));
const util_1 = __importDefault(require("util"));
const strip_ansi_1 = __importDefault(require("strip-ansi"));
const clr_1 = __importDefault(require("./clr"));
const errors_1 = require("@mongosh/errors");
exports.CONTROL_CHAR_REGEXP = /[\x00-\x1F\x7F-\x9F]/;
exports.CONTROL_CHAR_REGEXP_ALLOW_SIMPLE = /[\x00-\x08\x0B-\x1F\x7F-\x9F]/;
exports.fullDepthInspectOptions = {
    depth: Infinity,
    maxArrayLength: Infinity,
    maxStringLength: Infinity,
};
function formatBytes(value) {
    const precision = value <= 1000 ? '0' : '0.00';
    return (0, numeral_1.default)(value).format(precision + ' ib');
}
function formatOutput(evaluationResult, options) {
    const { value, type } = evaluationResult;
    if (type === 'Cursor' || type === 'AggregationCursor') {
        return formatCursor(value, { ...options, ...exports.fullDepthInspectOptions });
    }
    if (type === 'CursorIterationResult') {
        return formatCursorIterationResult(value, {
            ...options,
            ...exports.fullDepthInspectOptions,
        });
    }
    if (type === 'Help') {
        return formatHelp(value, options);
    }
    if (type === 'ShowDatabasesResult') {
        return formatDatabases(value, options);
    }
    if (type === 'ShowCollectionsResult') {
        return formatCollections(value, options);
    }
    if (type === 'ShowBannerResult') {
        return formatBanner(value, options);
    }
    if (type === 'StatsResult') {
        return formatStats(value, options);
    }
    if (type === 'ListCommandsResult') {
        return formatListCommands(value, options);
    }
    if (type === 'StreamsListResult') {
        return inspect(value, {
            ...options,
            ...exports.fullDepthInspectOptions,
        });
    }
    if (type === 'ShowProfileResult') {
        if (value.count === 0) {
            return (0, clr_1.default)(`db.system.profile is empty.
Use db.setProfilingLevel(2) will enable profiling.
Use db.getCollection('system.profile').find() to show raw profile entries.`, 'yellow', options);
        }
        return value.result
            .map(function (x) {
            const res = `${x.op}\t${x.ns} ${x.millis}ms ${String(x.ts).substring(0, 24)}\n`;
            let l = '';
            for (const z in x) {
                if (z === 'op' || z === 'ns' || z === 'millis' || z === 'ts') {
                    continue;
                }
                const val = x[z];
                const mytype = typeof val;
                if (mytype === 'object') {
                    l += z + ':' + formatSimpleType(val, options) + ' ';
                }
                else if (mytype === 'boolean') {
                    l += z + ' ';
                }
                else {
                    l += z + ':' + val + ' ';
                }
            }
            return `${res}${l}`;
        })
            .join('\n');
    }
    if (type === 'Error') {
        return formatError(value, options);
    }
    if (type === 'ExplainOutput' || type === 'ExplainableCursor') {
        return formatSimpleType(value, {
            ...options,
            ...exports.fullDepthInspectOptions,
        });
    }
    return formatSimpleType(value, options);
}
function formatSimpleType(output, options) {
    if (typeof output === 'string' &&
        (options.allowControlCharacters ||
            !exports.CONTROL_CHAR_REGEXP_ALLOW_SIMPLE.test(output))) {
        return output;
    }
    if (typeof output === 'undefined')
        return '';
    return inspect(output, options);
}
function formatCollections(output, options) {
    const systemCollections = [];
    const otherCollections = [];
    for (const coll of output) {
        if (coll.name.startsWith('system.') || coll.name.startsWith('enxcol_.')) {
            systemCollections.push(coll);
        }
        else {
            otherCollections.push(coll);
        }
    }
    const tableEntries = [
        ...otherCollections.map((coll) => [
            (0, clr_1.default)(formatSimpleType(coll.name, options), 'bold', options),
            coll.badge,
        ]),
        ...systemCollections.map((coll) => [
            `${options.colors ? '\u001b[2m' : ''}${(0, clr_1.default)(formatSimpleType(coll.name, options), 'bold', options)}`,
            coll.badge,
        ]),
    ];
    return (0, text_table_1.default)(tableEntries, { align: ['l', 'l'] });
}
function formatBanner(output, options) {
    if (!output?.content) {
        return '';
    }
    let text = '';
    text += `${(0, clr_1.default)('------', 'mongosh:section-header', options)}\n`;
    if (output.header) {
        text += `   ${(0, clr_1.default)(formatSimpleType(output.header, options), 'mongosh:section-header', options)}\n`;
    }
    text +=
        formatSimpleType(output.content, options).trim().replace(/^/gm, '   ') +
            '\n';
    text += `${(0, clr_1.default)('------', 'mongosh:section-header', options)}\n`;
    return text;
}
function formatDatabases(output, options) {
    const tableEntries = output.map((db) => [
        (0, clr_1.default)(formatSimpleType(db.name, options), 'bold', options),
        formatBytes(db.sizeOnDisk),
    ]);
    return (0, text_table_1.default)(tableEntries, { align: ['l', 'r'] });
}
function formatStats(output, options) {
    return Object.keys(output)
        .map((c) => {
        return (`${(0, clr_1.default)(formatSimpleType(c, options), 'mongosh:section-header', options)}\n` + `${inspect(output[c], options)}`);
    })
        .join('\n---\n');
}
function formatListCommands(output, options) {
    const tableEntries = Object.keys(output).map((cmd) => {
        const val = output[cmd];
        let result = `${(0, clr_1.default)(cmd, 'mongosh:section-header', options)}: `;
        for (const key of Object.keys(val)) {
            if (val[key] === true)
                result += ` ${(0, clr_1.default)(formatSimpleType(key, options), ['bold', 'white'], options)}`;
        }
        if (val.help) {
            result += `\n${(0, clr_1.default)(formatSimpleType(val.help, options), 'green', options)}`;
        }
        if (Array.isArray(val.apiVersions) && val.apiVersions.length > 0) {
            result += `\n${(0, clr_1.default)('API Versions', ['bold', 'white'], options)} ${formatSimpleType(val.apiVersions.join(', '), options)}`;
        }
        if (Array.isArray(val.deprecatedApiVersions) &&
            val.deprecatedApiVersions.length > 0) {
            result += `\n${(0, clr_1.default)('Deprecated API Versions', ['white'], options)} ${formatSimpleType(val.deprecatedApiVersions.join(', '), options)}`;
        }
        return result;
    });
    return tableEntries.join('\n\n');
}
function formatError(error, options) {
    let result = '';
    if (error.name) {
        result += `\r${(0, clr_1.default)(error.name, 'mongosh:error', options)}`;
        const codeName = error.codeName;
        if (codeName)
            result += `${(0, clr_1.default)(`[` + formatSimpleType(codeName, options) + `]`, 'mongosh:error', options)}`;
        result += ': ';
    }
    if (error.message && String(error.name).startsWith('Mongo')) {
        result += formatSimpleType(error.message, options);
    }
    else if (error.message) {
        result += error.message;
    }
    if ((0, errors_1.isShouldReportAsBugError)(error)) {
        result +=
            '\nThis is an error inside mongosh. Please file a bug report for the MONGOSH project here: https://jira.mongodb.org/projects/MONGOSH/issues.';
        if (options.bugReportErrorMessageInfo) {
            result += `\n${options.bugReportErrorMessageInfo}`;
        }
    }
    if (error.name === 'SyntaxError') {
        if (!options.colors) {
            result = (0, strip_ansi_1.default)(result);
        }
        result += '\n\n';
    }
    else if (options.showStackTraces && error.stack) {
        result += error.stack.slice(error.stack.indexOf('\n'));
    }
    if (error.errInfo) {
        result += `\n${(0, clr_1.default)(i18n_1.default.__('cli-repl.cli-repl.additionalErrorInfo'), 'mongosh:additional-error-info', options)}: `;
        result += inspect(error.errInfo, {
            ...options,
            ...exports.fullDepthInspectOptions,
        });
    }
    if (error.result) {
        result += `\n${(0, clr_1.default)(i18n_1.default.__('cli-repl.cli-repl.additionalErrorResult'), 'mongosh:additional-error-info', options)}: `;
        result += inspect(error.result, {
            ...options,
            ...exports.fullDepthInspectOptions,
        });
    }
    if (error.writeErrors) {
        result += `\n${(0, clr_1.default)(i18n_1.default.__('cli-repl.cli-repl.additionalErrorWriteErrors'), 'mongosh:additional-error-info', options)}: `;
        result += inspect(error.writeErrors, {
            ...options,
            ...exports.fullDepthInspectOptions,
        });
    }
    if (error.violations) {
        result += `\n${(0, clr_1.default)(i18n_1.default.__('cli-repl.cli-repl.additionalErrorViolations'), 'mongosh:additional-error-info', options)}: `;
        result += inspect(error.violations, {
            ...options,
            ...exports.fullDepthInspectOptions,
        });
    }
    if (error.cause) {
        result += `\n${(0, clr_1.default)(i18n_1.default.__('cli-repl.cli-repl.errorCausedBy'), 'mongosh:additional-error-info', options)}: \n`;
        const { cause } = error;
        result +=
            Object.prototype.toString.call(cause) === '[object Error]'
                ? formatError(cause, options)
                : inspect(cause, options);
    }
    return result;
}
function removeUndefinedValues(obj) {
    return Object.fromEntries(Object.entries(obj).filter((keyValue) => keyValue[1] !== undefined));
}
function dateInspect(depth, options) {
    if (isNaN(this.valueOf())) {
        return options.stylize('Invalid Date', 'date');
    }
    return `ISODate('${this.toISOString()}')`;
}
function inspect(output, options) {
    const originalDateInspect = Date.prototype[util_1.default.inspect.custom];
    Date.prototype[util_1.default.inspect.custom] = dateInspect;
    try {
        return util_1.default.inspect(output, removeUndefinedValues({
            showProxy: false,
            colors: options.colors ?? true,
            depth: options.depth ?? 6,
            maxArrayLength: options.maxArrayLength,
            maxStringLength: options.maxStringLength,
            compact: options.compact,
        }));
    }
    finally {
        delete Date.prototype[util_1.default.inspect.custom];
        if (originalDateInspect)
            Date.prototype[util_1.default.inspect.custom] = originalDateInspect;
    }
}
function formatCursor(value, options) {
    if (!value.documents?.length) {
        return '';
    }
    return formatCursorIterationResult(value, options);
}
function formatCursorIterationResult(value, options) {
    if (!value.documents?.length) {
        return i18n_1.default.__('shell-api.classes.Cursor.iteration.no-cursor');
    }
    let ret = inspect(value.documents, options);
    if (value.cursorHasMore) {
        ret +=
            '\n' + i18n_1.default.__('shell-api.classes.Cursor.iteration.type-it-for-more');
    }
    return ret;
}
function formatHelp(value, options) {
    const argLen = 47;
    let helpMenu = '';
    if (value.help) {
        helpMenu += `\n  ${(0, clr_1.default)(`${value.help}:`, 'mongosh:section-header', options)}\n\n`;
    }
    for (const method of value.attr || []) {
        let formatted = '';
        if (method.name && method.description) {
            formatted = `    ${method.name}`;
            const extraSpaces = argLen - formatted.length;
            const descriptionLines = method.description.split('\n');
            descriptionLines[0] = ' '.repeat(extraSpaces) + descriptionLines[0];
            for (let i = 1; i < descriptionLines.length; i++) {
                if (descriptionLines[i].trim() !== '') {
                    descriptionLines[i] = ' '.repeat(argLen) + descriptionLines[i];
                }
            }
            formatted += descriptionLines.join('\n');
        }
        if (!method.name && method.description) {
            formatted = `  ${method.description}`;
        }
        if (formatted !== '') {
            helpMenu += `${formatted}\n`;
        }
    }
    if (value.docs) {
        helpMenu +=
            `\n  ${(0, clr_1.default)(i18n_1.default.__('cli-repl.args.moreInformation'), 'bold', options)} ` +
                `${(0, clr_1.default)(value.docs, 'mongosh:uri', options)}`;
    }
    return helpMenu;
}
//# sourceMappingURL=format-output.js.map