"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderMarkdownForTerminal = renderMarkdownForTerminal;
const terminal_1 = require("./terminal");
const ANSI_REGEX = /\x1b\[[0-9;]*m/g;
function stripBlockquotePrefix(line) {
    return line.replace(/^\s*>+\s?/, "");
}
function visibleLength(value) {
    return value.replace(ANSI_REGEX, "").length;
}
function renderInlineMarkdown(text) {
    let rendered = text;
    rendered = rendered.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_match, altText) => {
        const alt = altText.trim();
        return alt.length > 0 ? alt : "[image]";
    });
    rendered = rendered.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1 ($2)");
    rendered = rendered.replace(/`([^`]+)`/g, (_match, code) => (0, terminal_1.colorize)(code, terminal_1.ansi.yellow));
    rendered = rendered.replace(/\*\*([^*]+)\*\*/g, (_match, boldText) => `${terminal_1.ansi.bold}${boldText}${terminal_1.ansi.reset}`);
    rendered = rendered.replace(/__([^_]+)__/g, (_match, boldText) => `${terminal_1.ansi.bold}${boldText}${terminal_1.ansi.reset}`);
    rendered = rendered.replace(/~~([^~]+)~~/g, "$1");
    return rendered;
}
function isMarkdownTableSeparator(line) {
    return /^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(line);
}
function isMarkdownTableRow(line) {
    const trimmed = line.trim();
    return trimmed.length > 0 && trimmed.includes("|");
}
function parseMarkdownTableRow(line) {
    const trimmed = line.trim().replace(/^\|/, "").replace(/\|$/, "");
    return trimmed.split("|").map((cell) => cell.trim());
}
function formatMarkdownTable(tableLines) {
    const rows = tableLines.map(parseMarkdownTableRow).filter((row) => row.length > 0);
    if (rows.length === 0) {
        return [];
    }
    const columnCount = Math.max(...rows.map((row) => row.length));
    const normalizedRows = rows.map((row) => {
        const cells = [...row];
        while (cells.length < columnCount) {
            cells.push("");
        }
        return cells;
    });
    const renderedRows = normalizedRows.map((row) => row.map((cell) => renderInlineMarkdown(cell)));
    const columnWidths = new Array(columnCount).fill(0);
    renderedRows.forEach((row) => {
        row.forEach((cell, index) => {
            columnWidths[index] = Math.max(columnWidths[index], visibleLength(cell));
        });
    });
    const renderRow = (row, boldRow = false) => {
        const formattedCells = row.map((cell, index) => {
            const padding = Math.max(0, columnWidths[index] - visibleLength(cell));
            const padded = `${cell}${" ".repeat(padding)}`;
            return boldRow ? `${terminal_1.ansi.bold}${padded}${terminal_1.ansi.reset}` : padded;
        });
        return formattedCells.join(" | ");
    };
    const output = [renderRow(renderedRows[0], true)];
    output.push((0, terminal_1.colorize)(columnWidths.map((width) => "-".repeat(Math.max(width, 3))).join("-+-"), terminal_1.ansi.dim));
    for (let rowIndex = 1; rowIndex < renderedRows.length; rowIndex += 1) {
        output.push(renderRow(renderedRows[rowIndex]));
    }
    return output;
}
function compactBlankLines(lines) {
    const output = [];
    let blankCount = 0;
    lines.forEach((line) => {
        if (line.trim().length === 0) {
            blankCount += 1;
            if (blankCount <= 2) {
                output.push("");
            }
            return;
        }
        blankCount = 0;
        output.push(line);
    });
    return output;
}
function renderMarkdownForTerminal(markdown) {
    const sourceLines = markdown.replace(/\r/g, "").split("\n");
    const outputLines = [];
    let inCodeBlock = false;
    for (let index = 0; index < sourceLines.length; index += 1) {
        const line = stripBlockquotePrefix(sourceLines[index]);
        if (/^\s*```/.test(line)) {
            inCodeBlock = !inCodeBlock;
            continue;
        }
        if (inCodeBlock) {
            outputLines.push((0, terminal_1.colorize)(line, terminal_1.ansi.dim));
            continue;
        }
        const nextLine = index + 1 < sourceLines.length
            ? stripBlockquotePrefix(sourceLines[index + 1])
            : "";
        if (isMarkdownTableRow(line) && isMarkdownTableSeparator(nextLine)) {
            const tableLines = [line];
            index += 2;
            while (index < sourceLines.length) {
                const candidate = stripBlockquotePrefix(sourceLines[index]);
                if (!isMarkdownTableRow(candidate)) {
                    break;
                }
                tableLines.push(candidate);
                index += 1;
            }
            index -= 1;
            outputLines.push(...formatMarkdownTable(tableLines));
            continue;
        }
        const headingMatch = line.match(/^\s*(#{1,6})\s+(.*)$/);
        if (headingMatch) {
            outputLines.push(`${terminal_1.ansi.bold}${renderInlineMarkdown(headingMatch[2].trim())}${terminal_1.ansi.reset}`);
            continue;
        }
        if (/^\s*([-*_]\s*){3,}\s*$/.test(line)) {
            outputLines.push((0, terminal_1.colorize)("-".repeat(40), terminal_1.ansi.dim));
            continue;
        }
        if (/^\s*[-*+]\s+/.test(line)) {
            outputLines.push(renderInlineMarkdown(line.replace(/^\s*[-*+]\s+/, "- ")));
            continue;
        }
        if (/^\s*\d+\.\s+/.test(line)) {
            outputLines.push(renderInlineMarkdown(line.trim()));
            continue;
        }
        outputLines.push(renderInlineMarkdown(line));
    }
    return compactBlankLines(outputLines).join("\n");
}
