import type { RegexFlavourId } from "../../../model/flavour";
import type {
  RegexSyntaxRequest,
  RegexSyntaxResult,
  ReplacementSyntaxResult,
  SyntaxCoverage,
} from "../../../model/syntax";
import type {
  RegexSyntaxProvider,
  ReplacementSyntaxRequest,
} from "../../SyntaxProvider";
import {
  lexicalCoverage,
  parseLexicalPattern,
  type LexicalCaptureDialect,
} from "../lexical-captures";
import { parseJavaReplacement } from "./replacement";

const DIALECT: LexicalCaptureDialect = {
  flavour: "java",
  providerId: "regex-tools-java-lexical",
  providerVersion: "0.3.0",
  engineLabel: "TeaVM java.util.regex",
  extendedFlag: "x",
  quotedLiterals: true,
  namedCapture: (pattern, opener) => {
    const match = /^\(\?<([A-Za-z][A-Za-z0-9]*)>/u.exec(pattern.slice(opener));
    return match?.[1]
      ? { name: match[1], end: opener + match[0].length }
      : undefined;
  },
  unsupportedConstructs: [
    "complete structural nesting and quantifier ownership",
    "inline flag scope in normalized explanations",
    "character-class intersections and Unicode properties as structural nodes",
    "conditionals, assertions and backreferences as structural nodes",
  ],
};

export class JavaSyntaxProvider implements RegexSyntaxProvider {
  readonly id = DIALECT.providerId;
  readonly version = DIALECT.providerVersion;
  readonly supportedFlavours = ["java"] as const;

  async parsePattern(request: RegexSyntaxRequest): Promise<RegexSyntaxResult> {
    return parseLexicalPattern(request, DIALECT);
  }

  async parseReplacement(
    request: ReplacementSyntaxRequest,
  ): Promise<ReplacementSyntaxResult> {
    if (request.flavour !== "java") {
      throw new Error(`Unsupported replacement flavour: ${request.flavour}`);
    }
    return parseJavaReplacement(request.replacement, request.captureMetadata);
  }

  getCoverage(flavour: RegexFlavourId): SyntaxCoverage {
    return lexicalCoverage(flavour, DIALECT);
  }
}
