import { LogFormatter } from "@zuplo/core/cli";
import { readFile } from "node:fs/promises";
const logFormatter = new LogFormatter(async (path) => {
    return readFile(path, { encoding: "utf8" });
});
export function handleRuntimeStdio(stdout, stderr) {
    const classifiers = {
        isBarf(chunk) {
            const containsLlvmSymbolizerWarning = chunk.includes("Not symbolizing stack traces because $LLVM_SYMBOLIZER is not set");
            const containsRecursiveIsolateLockWarning = chunk.includes("took recursive isolate lock");
            const containsHexStack = /stack:( (0|[a-f\d]{4,})){3,}/.test(chunk);
            return (containsLlvmSymbolizerWarning ||
                containsRecursiveIsolateLockWarning ||
                containsHexStack);
        },
        isAddressInUse(chunk) {
            return chunk.includes("Address already in use; toString() = ");
        },
        isWarning(chunk) {
            return /\.c\+\+:\d+: warning:/.test(chunk);
        },
        isCodeMovedWarning(chunk) {
            return /CODE_MOVED for unknown code block/.test(chunk);
        },
        isAccessViolation(chunk) {
            return chunk.includes("access violation;");
        },
        isZenoLog(chunk) {
            return chunk.startsWith("[ZENO]:");
        },
    };
    stdout.on("data", (chunk) => {
        chunk = chunk.toString().trim();
        if (classifiers.isBarf(chunk)) {
            logConsole("debug", chunk);
        }
        else if (classifiers.isWarning(chunk)) {
            logConsole("warn", chunk);
        }
        else if (classifiers.isZenoLog(chunk)) {
            const levels = ["debug", "info", "warn", "error"];
            const level = levels.find((level) => chunk.includes(`[${level.toUpperCase()}]`));
            chunk = chunk.substring("[ZENO]:".length);
            chunk = chunk.substring(`[${level?.toUpperCase()}]`.length);
            if (level) {
                logConsole(level, chunk);
            }
            else {
                logConsole("info", chunk);
            }
        }
        else {
            logConsole("error", chunk);
        }
    });
    stderr.on("data", (chunk) => {
        chunk = chunk.toString().trim();
        if (classifiers.isBarf(chunk)) {
            if (classifiers.isAddressInUse(chunk)) {
                const address = chunk.match(/Address already in use; toString\(\) = (.+)\n/)?.[1];
                logConsole("error", `Address already in use (${address}). Please check that you are not already running a server on this address or specify a different port with --port.`);
                logConsole("debug", chunk);
            }
            else if (classifiers.isAccessViolation(chunk)) {
                let error = "There was an access violation in the runtime.";
                if (process.platform === "win32") {
                    error +=
                        "\nOn Windows, this may be caused by an outdated Microsoft Visual C++ Redistributable library.\n" +
                            "Check that you have the latest version installed.\n" +
                            "See https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist.";
                }
                logConsole("error", error);
                logConsole("debug", chunk);
            }
            else {
                logConsole("debug", chunk);
            }
        }
        else if (classifiers.isWarning(chunk)) {
            logConsole("warn", chunk);
        }
        else if (classifiers.isCodeMovedWarning(chunk)) {
        }
        else if (classifiers.isZenoLog(chunk)) {
            chunk = chunk.substring("[ZENO]:".length);
            chunk = chunk.substring("[ERROR]".length);
            logConsole("error", chunk);
        }
        else {
            logConsole("error", chunk);
        }
    });
}
export function logConsole(level, data, callDepth = 0) {
    void logConsoleAsync(level, data, callDepth);
}
export async function logConsoleAsync(level, data, callDepth = 0) {
    try {
        if (!data) {
            return;
        }
        if (typeof data !== "string") {
            console[level](data);
            return;
        }
        let message = data?.trim();
        if (!message || message?.length === 0) {
            return;
        }
        if (message.startsWith(`{`) && message.endsWith(`}`)) {
            let logEntry;
            try {
                logEntry = JSON.parse(message);
            }
            catch {
                if (callDepth === 1) {
                    const lines = message.split("\n");
                    await Promise.all(lines.map(async (line) => logConsole(level, line, callDepth++)));
                    return;
                }
                else {
                    console[level](data);
                    return;
                }
            }
            await Promise.all(logEntry.messages.map(async (msg) => {
                const line = await logFormatter.formatStructured(logEntry, msg);
                console[level](line);
            }));
        }
        else {
            message = await logFormatter.formatMessage(message);
            const line = logFormatter.formatLine(level, message);
            console[level](line);
        }
    }
    catch {
        const line = logFormatter.formatLine(level, data);
        console[level](line);
    }
}
//# sourceMappingURL=worker-output.js.map