/**
 * A newline line-splitter for streamed child-process output (audit CC3/CC4/SIMP5).
 *
 * `download.ts` and `terminal.ts` each had the same hand-rolled loop: accumulate
 * chunk strings, emit every complete `\n`-terminated line (stripping a trailing
 * `\r`), and keep the partial remainder for the next chunk. This is that logic in
 * one place, and — being pure and synchronous — it's unit-tested directly.
 *
 * Usage: feed decoded chunks with `push()`, and call `flush()` on stream close to
 * emit any trailing partial line that never saw a newline.
 */
export interface LineBuffer {
  /** Accept a decoded chunk; invokes the sink for each newly-completed line. */
  push: (chunk: string) => void
  /** Emit any buffered remainder (a final line with no trailing newline). */
  flush: () => void
}

export function createLineBuffer(onLine: (line: string) => void): LineBuffer {
  let buf = ''
  return {
    push(chunk: string): void {
      buf += chunk
      let nl: number
      while ((nl = buf.indexOf('\n')) >= 0) {
        onLine(buf.slice(0, nl).replace(/\r$/, ''))
        buf = buf.slice(nl + 1)
      }
    },
    flush(): void {
      if (buf) {
        onLine(buf)
        buf = ''
      }
    }
  }
}
