"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.patchErrorFunction = void 0;
const debugFunctions_1 = require("./functions/debugFunctions");
const LINE_SEPARATOR = "\n";
/**
 * These must be listed in order from how they appear in the traceback from top to bottom, or they
 * won't be properly removed.
 */
const USELESS_TRACEBACK_MESSAGES = [
    // The second line of the traceback will always be the "getTraceback" function.
    "in upvalue 'getTraceback'",
    "in function 'sandbox.GetTraceback'",
    // The third line of the traceback will always be a line within the "errorWithTraceback" function.
    "in function 'error'",
];
let vanillaError;
/**
 * In Lua, the `error` function will tell you the line number of the error, but not give you a full
 * traceback of the parent functions, which is unlike how JavaScript works. This function monkey
 * patches the `error` function to add this functionality.
 *
 * Traceback functionality can only be added if the "--luadebug" flag is turned on, so this function
 * does nothing if the "--luadebug" flag is disabled.
 */
function patchErrorFunction() {
    // Only replace the function if the "--luadebug" launch flag is enabled.
    if (!(0, debugFunctions_1.isLuaDebugEnabled)()) {
        return;
    }
    // Do nothing if the function was already patched.
    if (__PATCHED_ERROR !== undefined) {
        return;
    }
    __PATCHED_ERROR = true;
    vanillaError = error;
    error = errorWithTraceback;
}
exports.patchErrorFunction = patchErrorFunction;
function errorWithTraceback(message, level = 1) {
    if (vanillaError === undefined) {
        error(message, level);
    }
    const tracebackOutput = (0, debugFunctions_1.getTraceback)();
    const slimmedTracebackOutput = slimTracebackOutput(tracebackOutput);
    message += "\n";
    message += slimmedTracebackOutput;
    // We add one to the level so that the error message appears to originate at the parent function.
    return vanillaError(message, level + 1);
}
/**
 * Some lines of the traceback output will not be relevant to the error that just occurred. Thus, to
 * reduce noise, we can always remove these lines.
 */
function slimTracebackOutput(tracebackOutput) {
    for (const msg of USELESS_TRACEBACK_MESSAGES) {
        tracebackOutput = removeLinesContaining(tracebackOutput, msg);
    }
    return tracebackOutput;
}
function removeLinesContaining(msg, containsMsg) {
    const lines = msg.split(LINE_SEPARATOR);
    const linesThatDontContain = lines.filter((line) => !line.includes(containsMsg));
    return linesThatDontContain.join(LINE_SEPARATOR);
}
