import type { RegexDiagnostic } from "./diagnostics";
import type {
  RegexEngineInfo,
  RegexEngineOptions,
  RegexFlavourId,
} from "./flavour";
import type { CaptureDefinition, SourceRange } from "./syntax";

export interface NativeTextRange {
  readonly start: number;
  readonly end: number;
  readonly unit: "utf16" | "code-point" | "utf8-byte" | "byte";
}

export interface CaptureResult {
  readonly groupNumber: number;
  readonly groupName?: string;
  readonly value?: string;
  readonly status:
    | "participated"
    | "did-not-participate"
    | "matched-empty"
    | "truncated"
    | "unavailable";
  readonly range?: SourceRange;
  readonly nativeRange?: NativeTextRange;
}

export interface RegexMatchResult {
  readonly matchNumber: number;
  readonly value: string;
  readonly valueStatus: "complete" | "truncated";
  readonly range: SourceRange;
  readonly nativeRange: NativeTextRange;
  readonly captures: readonly CaptureResult[];
}

export interface RegexExecutionFlags {
  readonly userFlags: string;
  readonly effectiveFlags: string;
  readonly internallyAddedIndicesFlag: boolean;
  readonly internallyAddedGlobalFlag: boolean;
}

export interface RegexExecutionRequest {
  readonly flavour: RegexFlavourId;
  readonly flavourVersion?: string;
  readonly pattern: string;
  readonly flags: readonly string[];
  readonly options?: RegexEngineOptions;
  readonly subject: string;
  readonly captureMetadata: readonly CaptureDefinition[];
  readonly scanAll: boolean;
  readonly maximumMatches: number;
  readonly maximumCaptureRows: number;
}

export interface RegexExecutionResult {
  readonly accepted: boolean;
  readonly engine: RegexEngineInfo;
  readonly flags: RegexExecutionFlags;
  readonly matches: readonly RegexMatchResult[];
  readonly diagnostics: readonly RegexDiagnostic[];
  readonly elapsedMs: number;
  readonly truncated: boolean;
}

export interface RegexReplacementRequest extends RegexExecutionRequest {
  readonly replacement: string;
  readonly maximumOutputBytes: number;
}

export interface RegexReplacementResult {
  readonly execution: RegexExecutionResult;
  readonly output: string;
  readonly outputBytes: number;
  /** The materialized output stopped at maximumOutputBytes. */
  readonly outputTruncated: boolean;
  /** The output or its authoritative match collection is incomplete. */
  readonly truncated: boolean;
}

export interface ExtractionNode {
  readonly id: string;
  readonly kind: "match" | "capture" | "capture-history" | "derived";
  readonly label: string;
  readonly groupNumber?: number;
  readonly groupName?: string;
  readonly value?: string;
  readonly range?: SourceRange;
  readonly nativeRange?: NativeTextRange;
  readonly status:
    | "participated"
    | "did-not-participate"
    | "matched-empty"
    | "truncated"
    | "unavailable";
  readonly children: readonly ExtractionNode[];
  readonly provenance:
    | "engine-result"
    | "engine-capture-history"
    | "engine-trace"
    | "derived-from-syntax"
    | "inferred";
}
