/**
 * Line-buffered, prefixed writer for task-level parallel execution.
 *
 * When multiple tasks run concurrently (takt run --concurrency N), each task's
 * output must be identifiable and line-aligned to prevent mid-line interleaving.
 * This class wraps process.stdout.write with line buffering and a colored
 * `[taskName]` prefix on every non-empty line.
 *
 * Design mirrors ParallelLogger (step-level) but targets task-level output:
 * - Regular log lines (info, header, status) get the prefix
 * - Stream output gets line-buffered then prefixed
 * - Empty lines are passed through without prefix
 */
import { stripAnsi } from '../utils/text.js';
/** ANSI color codes for task prefixes (cycled by task index) */
const TASK_COLORS = ['\x1b[36m', '\x1b[33m', '\x1b[35m', '\x1b[32m'];
const RESET = '\x1b[0m';
/**
 * Prefixed line writer for a single parallel task.
 *
 * All output goes through `writeLine` (complete lines) or `writeChunk`
 * (buffered partial lines). The prefix `[taskName]` is prepended to every
 * non-empty output line.
 */
export class TaskPrefixWriter {
    taskPrefix;
    writeFn;
    stepContext;
    lineBuffer = '';
    constructor(options) {
        const color = TASK_COLORS[options.colorIndex % TASK_COLORS.length];
        const issueLabel = options.issue == null ? undefined : `#${options.issue}`;
        const taskLabel = issueLabel ?? options.displayLabel ?? options.taskName.slice(0, 4);
        this.taskPrefix = `${color}[${taskLabel}]${RESET}`;
        this.writeFn = options.writeFn ?? ((text) => process.stdout.write(text));
    }
    setStepContext(context) {
        this.stepContext = context;
    }
    buildPrefix() {
        if (!this.stepContext) {
            return `${this.taskPrefix} `;
        }
        const { stepName, iteration, maxSteps, stepIteration } = this.stepContext;
        return `${this.taskPrefix}[${stepName}](${iteration}/${maxSteps})(${stepIteration}) `;
    }
    /**
     * Write a complete line with prefix.
     * Multi-line text is split and each non-empty line gets the prefix.
     * Optional style function is applied after ANSI stripping.
     */
    writeLine(text, style) {
        const cleaned = stripAnsi(text);
        const lines = cleaned.split('\n');
        for (const line of lines) {
            if (line === '') {
                this.writeFn('\n');
            }
            else {
                const output = style ? style(line) : line;
                this.writeFn(`${this.buildPrefix()}${output}\n`);
            }
        }
    }
    /**
     * Write a chunk of streaming text with line buffering.
     * Partial lines are buffered until a newline arrives, then output with prefix.
     * Optional style function is applied after ANSI stripping.
     */
    writeChunk(text, style) {
        const cleaned = stripAnsi(text);
        const combined = this.lineBuffer + cleaned;
        const parts = combined.split('\n');
        const remainder = parts.pop() ?? '';
        this.lineBuffer = remainder;
        for (const line of parts) {
            if (line === '') {
                this.writeFn('\n');
            }
            else {
                const output = style ? style(line) : line;
                this.writeFn(`${this.buildPrefix()}${output}\n`);
            }
        }
    }
    /**
     * Flush any remaining buffered content.
     */
    flush() {
        if (this.lineBuffer !== '') {
            this.writeFn(`${this.buildPrefix()}${this.lineBuffer}\n`);
            this.lineBuffer = '';
        }
    }
}
//# sourceMappingURL=TaskPrefixWriter.js.map