/**
 * TUI renderers for file operation tools (read, write, edit).
 *
 * Each tool has a renderCall (header) and renderResult (output/diff) function.
 * Write and edit renderers support live preview via ToolExecutionPreviewState
 * (syntax highlighting cache, diff preview).
 */
import { Text } from '../../../../tui/index.js';
import { formatSize } from '../../../../utils/truncate.js';
import { getLanguageFromPath, highlightCode } from '../../../theme/theme.js';
import { renderDiff } from '../../runtime/diff.js';
import { coerceToolString, normalizeToolText, shortenHomePath } from '../../runtime/tool-execution-types.js';
function invalidArg(theme) {
    return theme.fg('error', '[invalid arg]');
}
export function renderReadCall(args, theme) {
    const parsedArgs = (args ?? {});
    const rawPath = coerceToolString(parsedArgs.file_path ?? parsedArgs.path);
    const path = rawPath !== null ? shortenHomePath(rawPath) : null;
    const offset = typeof parsedArgs.offset === 'number' ? parsedArgs.offset : undefined;
    const limit = typeof parsedArgs.limit === 'number' ? parsedArgs.limit : undefined;
    let pathDisplay = path === null
        ? invalidArg(theme)
        : path
            ? theme.fg('accent', path)
            : theme.fg('toolOutput', '...');
    if (offset !== undefined || limit !== undefined) {
        const startLine = offset ?? 1;
        const endLine = limit !== undefined ? startLine + limit - 1 : '';
        pathDisplay += theme.fg('warning', `:${startLine}${endLine ? `-${endLine}` : ''}`);
    }
    return new Text(`${theme.fg('toolTitle', theme.bold('read'))} ${pathDisplay}`, 0, 0);
}
export function renderReadResult(args, result, expanded, textOutput, theme) {
    if (!result || !textOutput) {
        return undefined;
    }
    const parsedArgs = (args ?? {});
    const rawPath = coerceToolString(parsedArgs.file_path ?? parsedArgs.path);
    const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
    const lines = lang ? highlightCode(normalizeToolText(textOutput), lang) : textOutput.split('\n');
    const totalLines = lines.length;
    const collapsedLines = 2;
    const displayLines = expanded ? lines : lines.slice(-collapsedLines);
    const skipped = expanded ? 0 : Math.max(0, totalLines - collapsedLines);
    const chunks = [];
    chunks.push(displayLines
        .map((line) => lang ? normalizeToolText(line) : theme.fg('toolOutput', normalizeToolText(line)))
        .join('\n'));
    if (skipped > 0) {
        chunks.push(theme.fg('muted', `... +${skipped} lines`));
    }
    const truncation = result.details?.truncation;
    if (expanded && truncation?.truncated) {
        chunks.push(theme.fg('warning', `[Truncated: showing ${formatSize(truncation.outputChars)} of ${formatSize(truncation.totalChars)}]`));
    }
    return new Text(chunks.join('\n'), 0, 0);
}
export function renderWriteCall(args, expanded, preview, theme) {
    const parsedArgs = (args ?? {});
    const rawPath = coerceToolString(parsedArgs.file_path ?? parsedArgs.path);
    const fileContent = coerceToolString(parsedArgs.content);
    const path = rawPath !== null ? shortenHomePath(rawPath) : null;
    let text = theme.fg('toolTitle', theme.bold('write')) +
        ' ' +
        (path === null
            ? invalidArg(theme)
            : path
                ? theme.fg('accent', path)
                : theme.fg('toolOutput', '...'));
    if (fileContent === null) {
        text += `\n\n${theme.fg('error', '[invalid content arg - expected string]')}`;
        return new Text(text, 0, 0);
    }
    if (!fileContent) {
        return new Text(text, 0, 0);
    }
    const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
    const { writeHighlightCache } = preview ?? {};
    const lines = lang
        ? writeHighlightCache &&
            writeHighlightCache.lang === lang &&
            writeHighlightCache.rawPath === rawPath &&
            writeHighlightCache.rawContent === fileContent
            ? writeHighlightCache.highlightedLines
            : highlightCode(normalizeToolText(fileContent), lang)
        : fileContent.split('\n');
    const totalLines = lines.length;
    const maxLines = expanded ? totalLines : 10;
    const displayLines = lines.slice(0, maxLines);
    const remaining = lines.length - maxLines;
    text +=
        '\n\n' +
            displayLines
                .map((line) => (lang ? line : theme.fg('toolOutput', normalizeToolText(line))))
                .join('\n');
    if (remaining > 0) {
        text += theme.fg('muted', `\n... (${remaining} more lines, ${totalLines} total)`);
    }
    return new Text(text, 0, 0);
}
export function renderWriteResult(result, textOutput, theme) {
    if (!result?.isError || !textOutput) {
        return undefined;
    }
    return new Text(theme.fg('errorDim', textOutput), 0, 0);
}
export function renderEditCall(args, preview, theme) {
    const parsedArgs = (args ?? {});
    const rawPath = coerceToolString(parsedArgs.file_path ?? parsedArgs.path);
    const path = rawPath !== null ? shortenHomePath(rawPath) : null;
    const { firstChangedLine } = preview ?? {};
    let pathDisplay = path === null
        ? invalidArg(theme)
        : path
            ? theme.fg('accent', path)
            : theme.fg('toolOutput', '...');
    if (firstChangedLine) {
        pathDisplay += theme.fg('warning', `:${firstChangedLine}`);
    }
    return new Text(`${theme.fg('toolTitle', theme.bold('edit'))} ${pathDisplay}`, 0, 0);
}
export function renderEditResult(args, result, expanded, textOutput, preview, theme) {
    if (result?.isError) {
        return textOutput ? new Text(theme.fg('errorDim', textOutput), 0, 0) : undefined;
    }
    if (!expanded) {
        return undefined;
    }
    const parsedArgs = (args ?? {});
    const rawPath = coerceToolString(parsedArgs.file_path ?? parsedArgs.path);
    const { editDiffPreview } = preview ?? {};
    if (result?.details?.diff) {
        return new Text(renderDiff(result.details.diff, { filePath: rawPath ?? undefined }), 0, 0);
    }
    if (editDiffPreview) {
        if ('error' in editDiffPreview) {
            return new Text(theme.fg('error', editDiffPreview.error), 0, 0);
        }
        if (editDiffPreview.diff) {
            return new Text(renderDiff(editDiffPreview.diff, { filePath: rawPath ?? undefined }), 0, 0);
        }
    }
    return undefined;
}
//# sourceMappingURL=file-ops.js.map