export class TerminalFrameRenderer {
    prevLines = [];
    mode;
    height;
    write;
    clearFrame;
    constructor(modeOrOptions = "diff", height) {
        if (typeof modeOrOptions === "string") {
            this.mode = modeOrOptions;
            this.height = height;
            this.write = (chunk) => process.stdout.write(chunk);
            this.clearFrame = () => clearTerminalScreen(this.write);
            return;
        }
        this.mode = modeOrOptions.mode ?? "diff";
        this.height = modeOrOptions.height;
        this.write = modeOrOptions.write ?? ((chunk) => process.stdout.write(chunk));
        this.clearFrame = modeOrOptions.clear ?? (() => clearTerminalScreen(this.write));
    }
    render(frame) {
        const newLines = frame.split("\n");
        if (this.mode === "full") {
            this.clear();
            const fillsFixedFrame = this.height != null && newLines.length >= Math.max(1, Math.floor(this.height));
            this.write(fillsFixedFrame ? frame : `${frame}\n`);
            this.prevLines = [...newLines];
            return;
        }
        if (this.mode === "append") {
            this.write(`${frame}\n`);
            this.prevLines = [...newLines];
            return;
        }
        const parts = ["\x1b[H"];
        const maxLen = Math.max(newLines.length, this.prevLines.length);
        for (let i = 0; i < maxLen; i++) {
            const newLine = newLines[i] ?? "";
            const oldLine = this.prevLines[i] ?? "";
            if (i < newLines.length) {
                if (newLine !== oldLine) {
                    parts.push(`${newLine}\x1b[K`);
                }
            }
            else {
                parts.push("\x1b[K");
            }
            if (i < maxLen - 1) {
                parts.push("\r\n");
            }
        }
        this.write(parts.join(""));
        this.prevLines = [...newLines];
    }
    clear() {
        this.clearFrame();
    }
}
export function clearTerminalScreen(write = (chunk) => process.stdout.write(chunk)) {
    write("\x1b[2J\x1b[H");
}
