import type { CaptureResult, RegexMatchResult } from "../model/match";
import { lineAndColumnsAt } from "../execution/offsets/line-offset-map";

export interface CaptureRow {
  readonly id: string;
  readonly matchNumber: number;
  readonly groupNumber: number;
  readonly groupName?: string;
  readonly status: CaptureResult["status"];
  readonly value?: string;
  readonly start?: number;
  readonly end?: number;
  readonly length?: number;
  readonly nativeStart?: number;
  readonly nativeEnd?: number;
  readonly nativeUnit?: string;
  readonly line?: number;
  readonly column?: number;
}

export function buildCaptureRows(
  matches: readonly RegexMatchResult[],
  subject: string,
): readonly CaptureRow[] {
  const positions = lineAndColumnsAt(
    subject,
    matches.flatMap((match) =>
      match.captures.flatMap((capture) =>
        capture.range ? [capture.range.startUtf16] : [],
      ),
    ),
  );
  return matches.flatMap((match) =>
    match.captures.map((capture) => {
      const position = capture.range
        ? positions.get(capture.range.startUtf16)
        : undefined;
      return {
        id: `row-${match.matchNumber}-${capture.groupNumber}`,
        matchNumber: match.matchNumber,
        groupNumber: capture.groupNumber,
        ...(capture.groupName ? { groupName: capture.groupName } : {}),
        status: capture.status,
        ...(capture.value === undefined ? {} : { value: capture.value }),
        ...(capture.range
          ? {
              start: capture.range.startUtf16,
              end: capture.range.endUtf16,
              length: capture.range.endUtf16 - capture.range.startUtf16,
            }
          : {}),
        ...(capture.nativeRange
          ? {
              nativeStart: capture.nativeRange.start,
              nativeEnd: capture.nativeRange.end,
              nativeUnit: capture.nativeRange.unit,
            }
          : {}),
        ...(position ? position : {}),
      };
    }),
  );
}
