import type { RegexFlavourId } from "../model/flavour";

export interface ReferenceEntry {
  readonly id: string;
  readonly construct: string;
  readonly syntax: string;
  readonly explanation: string;
  readonly flavours: readonly RegexFlavourId[];
  readonly flags: readonly string[];
  readonly example: string;
  readonly caveat?: string;
  readonly source: string;
  readonly sourceUrl: string;
}

const ECMASCRIPT_REFERENCE_SOURCE =
  "https://tc39.es/ecma262/multipage/text-processing.html#sec-regexp-regular-expression-objects";

const ECMASCRIPT_REFERENCE_ENTRIES: readonly Omit<
  ReferenceEntry,
  "flavours" | "sourceUrl"
>[] = [
  {
    id: "literal",
    construct: "Literal",
    syntax: "text",
    explanation: "Matches the same sequence of characters.",
    flags: [],
    example: "invoice",
    source: "ECMAScript RegExp grammar",
  },
  {
    id: "any",
    construct: "Any character",
    syntax: ".",
    explanation:
      "Matches one character, excluding line terminators unless dotAll is active.",
    flags: ["s"],
    example: "a.b",
    source: "ECMAScript Atom grammar",
  },
  {
    id: "class",
    construct: "Character class",
    syntax: "[A-Z]",
    explanation: "Matches one character represented by the class.",
    flags: ["i", "u", "v"],
    example: "[A-F0-9]",
    source: "ECMAScript ClassRanges grammar",
  },
  {
    id: "capture",
    construct: "Capture group",
    syntax: "(...)",
    explanation: "Groups constructs and retains the matched substring.",
    flags: [],
    example: "(\\d{4})",
    source: "ECMAScript Grouping grammar",
  },
  {
    id: "named-capture",
    construct: "Named capture",
    syntax: "(?<name>...)",
    explanation:
      "Retains the matched substring under a stable name and number.",
    flags: [],
    example: "(?<year>\\d{4})",
    source: "ECMAScript NamedCapturingGroup grammar",
  },
  {
    id: "noncapture",
    construct: "Non-capturing group",
    syntax: "(?:...)",
    explanation: "Groups constructs without creating a capture.",
    flags: [],
    example: "(?:https?|ftp)",
    source: "ECMAScript GroupSpecifier grammar",
  },
  {
    id: "quantifier",
    construct: "Bounded repetition",
    syntax: "{min,max}",
    explanation: "Repeats the preceding construct between the selected bounds.",
    flags: [],
    example: "\\d{2,4}",
    source: "ECMAScript QuantifierPrefix grammar",
  },
  {
    id: "lookahead",
    construct: "Lookahead",
    syntax: "(?=...)",
    explanation: "Requires a following match without consuming it.",
    flags: [],
    example: "\\d+(?= EUR)",
    source: "ECMAScript Assertion grammar",
  },
  {
    id: "lookbehind",
    construct: "Lookbehind",
    syntax: "(?<=...)",
    explanation: "Requires a preceding match without consuming it.",
    flags: [],
    example: "(?<=€)\\d+",
    source: "ECMAScript Assertion grammar",
  },
  {
    id: "property",
    construct: "Unicode property",
    syntax: "\\p{Property}",
    explanation: "Matches characters with the selected Unicode property.",
    flags: ["u", "v"],
    example: "\\p{Letter}+",
    caveat: "Requires Unicode or Unicode-sets mode.",
    source: "ECMAScript UnicodePropertyValueExpression grammar",
  },
  {
    id: "backreference",
    construct: "Named backreference",
    syntax: "\\k<name>",
    explanation: "Matches the text retained by an earlier named capture.",
    flags: [],
    example: "(?<word>\\w+)\\s+\\k<word>",
    source: "ECMAScript AtomEscape grammar",
  },
  {
    id: "anchor",
    construct: "Input anchors",
    syntax: "^  $",
    explanation:
      "Assert the beginning or end of input; multiline mode also considers lines.",
    flags: ["m"],
    example: "^ERROR:.*$",
    source: "ECMAScript Assertion grammar",
  },
];

export const ECMASCRIPT_REFERENCE: readonly ReferenceEntry[] =
  ECMASCRIPT_REFERENCE_ENTRIES.map((entry) => ({
    ...entry,
    flavours: ["ecmascript"],
    sourceUrl: ECMASCRIPT_REFERENCE_SOURCE,
  }));

const PCRE2_REFERENCE_SOURCE =
  "https://www.pcre.org/current/doc/html/pcre2pattern.html";

export const PCRE2_REFERENCE: readonly ReferenceEntry[] = [
  {
    id: "pcre2-named-capture",
    construct: "Named capture",
    syntax: "(?<name>...)",
    explanation:
      "Captures under a number and name; PCRE2 also accepts (?'name'...) and (?P<name>...).",
    flavours: ["pcre2"],
    flags: [],
    example: "(?<year>\\d{4})",
    source: "PCRE2 pattern documentation",
    sourceUrl: PCRE2_REFERENCE_SOURCE,
  },
  {
    id: "pcre2-branch-reset",
    construct: "Branch-reset group",
    syntax: "(?|...|...)",
    explanation:
      "Alternatives reuse the same capture numbers, which is useful for stable extraction schemas.",
    flavours: ["pcre2"],
    flags: [],
    example: "(?|(a)|(b))-(\\d+)",
    source: "PCRE2 pattern documentation",
    sourceUrl: PCRE2_REFERENCE_SOURCE,
  },
  {
    id: "pcre2-atomic",
    construct: "Atomic group",
    syntax: "(?>...)",
    explanation: "Prevents backtracking into the group after it has matched.",
    flavours: ["pcre2"],
    flags: [],
    example: "(?>\\d+)\\d",
    source: "PCRE2 pattern documentation",
    sourceUrl: PCRE2_REFERENCE_SOURCE,
  },
  {
    id: "pcre2-possessive",
    construct: "Possessive quantifier",
    syntax: "++  *+  ?+  {m,n}+",
    explanation:
      "Repeats without giving characters back during later backtracking.",
    flavours: ["pcre2"],
    flags: [],
    example: "\\w++:",
    source: "PCRE2 pattern documentation",
    sourceUrl: PCRE2_REFERENCE_SOURCE,
  },
  {
    id: "pcre2-subroutine",
    construct: "Named subroutine",
    syntax: "(?&name)",
    explanation: "Invokes an earlier named group as a subpattern.",
    flavours: ["pcre2"],
    flags: [],
    example: "(?<pair>\\((?:[^()]|(?&pair))*\\))",
    source: "PCRE2 pattern documentation",
    sourceUrl: PCRE2_REFERENCE_SOURCE,
  },
  {
    id: "pcre2-control-verb",
    construct: "Backtracking control",
    syntax: "(*SKIP)(*FAIL)",
    explanation:
      "Controls the engine search path; SKIP/FAIL is commonly used to exclude alternatives.",
    flavours: ["pcre2"],
    flags: [],
    example: '"[^"]*"(*SKIP)(*FAIL)|\\b\\w+\\b',
    source: "PCRE2 pattern documentation",
    sourceUrl: PCRE2_REFERENCE_SOURCE,
  },
  {
    id: "pcre2-extended",
    construct: "Extended layout",
    syntax: "whitespace  # comment",
    explanation:
      "Ignores unescaped layout whitespace and enables line comments outside classes.",
    flavours: ["pcre2"],
    flags: ["x"],
    example: "(?<year>\\d{4})  # year",
    source: "PCRE2 pattern documentation",
    sourceUrl: PCRE2_REFERENCE_SOURCE,
  },
  {
    id: "pcre2-unicode-property",
    construct: "Unicode property",
    syntax: "\\p{Property}",
    explanation:
      "Matches characters by Unicode property in the runtime's mandatory UTF/UCP mode.",
    flavours: ["pcre2"],
    flags: [],
    example: "\\p{L}+",
    caveat:
      "Regex Tools runs PCRE2 in UTF/UCP mode so native byte offsets always normalize safely to the browser editor.",
    source: "PCRE2 pattern documentation",
    sourceUrl: PCRE2_REFERENCE_SOURCE,
  },
];

const PYTHON_REFERENCE_SOURCE = "https://docs.python.org/3.14/library/re.html";

export const PYTHON_REFERENCE: readonly ReferenceEntry[] = [
  {
    id: "python-named-capture",
    construct: "Named capture",
    syntax: "(?P<name>...)",
    explanation:
      "Captures a group under both a number and a Python identifier.",
    flavours: ["python"],
    flags: [],
    example: "(?P<year>\\d{4})",
    source: "Python 3.14 re documentation",
    sourceUrl: PYTHON_REFERENCE_SOURCE,
  },
  {
    id: "python-named-backreference",
    construct: "Named backreference",
    syntax: "(?P=name)",
    explanation: "Matches the text retained by an earlier named capture.",
    flavours: ["python"],
    flags: [],
    example: "(?P<quote>['\"]).*?(?P=quote)",
    source: "Python 3.14 re documentation",
    sourceUrl: PYTHON_REFERENCE_SOURCE,
  },
  {
    id: "python-scoped-flags",
    construct: "Scoped inline flags",
    syntax: "(?aiLmsux-imsx:...)",
    explanation:
      "Applies selected matching modes only inside the enclosing group.",
    flavours: ["python"],
    flags: ["a", "i", "m", "s", "x"],
    example: "(?i:invoice)-(?a:\\w+)",
    caveat:
      "The a, L and u character-mode flags are mutually exclusive within one inline group.",
    source: "Python 3.14 re documentation",
    sourceUrl: PYTHON_REFERENCE_SOURCE,
  },
  {
    id: "python-atomic",
    construct: "Atomic group",
    syntax: "(?>...)",
    explanation:
      "Discards the group's internal backtracking points after it succeeds.",
    flavours: ["python"],
    flags: [],
    example: "(?>\\d+)\\d",
    source: "Python 3.14 re documentation",
    sourceUrl: PYTHON_REFERENCE_SOURCE,
  },
  {
    id: "python-possessive",
    construct: "Possessive quantifier",
    syntax: "*+  ++  ?+  {m,n}+",
    explanation:
      "Repeats without allowing later pattern parts to backtrack into the repetition.",
    flavours: ["python"],
    flags: [],
    example: "\\w++:",
    source: "Python 3.14 re documentation",
    sourceUrl: PYTHON_REFERENCE_SOURCE,
  },
  {
    id: "python-lookbehind",
    construct: "Fixed-length lookbehind",
    syntax: "(?<=...)  (?<!...)",
    explanation:
      "Checks immediately preceding text without consuming it; the contained pattern must have a fixed length.",
    flavours: ["python"],
    flags: [],
    example: "(?<=€)\\d+",
    caveat:
      "Alternatives and repetitions are accepted only when the lookbehind still has one fixed width.",
    source: "Python 3.14 re documentation",
    sourceUrl: PYTHON_REFERENCE_SOURCE,
  },
  {
    id: "python-conditional",
    construct: "Capture conditional",
    syntax: "(?(id/name)yes|no)",
    explanation:
      "Selects a branch according to whether an earlier capture participated.",
    flavours: ["python"],
    flags: [],
    example: "(<)?\\w+@(\\w+\\.)+\\w+(?(1)>|$)",
    source: "Python 3.14 re documentation",
    sourceUrl: PYTHON_REFERENCE_SOURCE,
  },
  {
    id: "python-absolute-end",
    construct: "Absolute end anchor",
    syntax: "\\z",
    explanation: "Asserts the absolute end of the input.",
    flavours: ["python"],
    flags: [],
    example: "\\d+\\z",
    caveat: "The \\z spelling was added in Python 3.14.",
    source: "Python 3.14 re documentation",
    sourceUrl: PYTHON_REFERENCE_SOURCE,
  },
];

const JAVA_REFERENCE_SOURCE =
  "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/regex/Pattern.html";

export const JAVA_REFERENCE: readonly ReferenceEntry[] = [
  {
    id: "java-named-capture",
    construct: "Named capture",
    syntax: "(?<name>...)",
    explanation:
      "Captures a group under both a number and a Latin-letter-led name.",
    flavours: ["java"],
    flags: [],
    example: "(?<year>\\d{4})",
    source: "Java SE 25 Pattern documentation",
    sourceUrl: JAVA_REFERENCE_SOURCE,
  },
  {
    id: "java-named-backreference",
    construct: "Named backreference",
    syntax: "\\k<name>",
    explanation: "Matches the text retained by an earlier named capture.",
    flavours: ["java"],
    flags: [],
    example: "(?<word>\\w+)\\s+\\k<word>",
    source: "Java SE 25 Pattern documentation",
    sourceUrl: JAVA_REFERENCE_SOURCE,
  },
  {
    id: "java-class-intersection",
    construct: "Character-class intersection",
    syntax: "[class&&class]",
    explanation:
      "Keeps only characters present in both nested character classes.",
    flavours: ["java"],
    flags: [],
    example: "[a-z&&[^aeiou]]+",
    source: "Java SE 25 Pattern documentation",
    sourceUrl: JAVA_REFERENCE_SOURCE,
  },
  {
    id: "java-scoped-flags",
    construct: "Scoped embedded flags",
    syntax: "(?idmsuxU-idmsuxU:...)",
    explanation: "Enables and disables selected Pattern modes for one group.",
    flavours: ["java"],
    flags: ["i", "d", "m", "s", "u", "x", "U"],
    example: "(?i:invoice)-(?-i:[A-Z]+)",
    source: "Java SE 25 Pattern documentation",
    sourceUrl: JAVA_REFERENCE_SOURCE,
  },
  {
    id: "java-independent",
    construct: "Independent group",
    syntax: "(?>...)",
    explanation:
      "Prevents the engine from revisiting choices made inside the group.",
    flavours: ["java"],
    flags: [],
    example: "(?>\\d+)\\d",
    source: "Java SE 25 Pattern documentation",
    sourceUrl: JAVA_REFERENCE_SOURCE,
  },
  {
    id: "java-possessive",
    construct: "Possessive quantifier",
    syntax: "*+  ++  ?+  {m,n}+",
    explanation:
      "Repeats without returning matched characters during later backtracking.",
    flavours: ["java"],
    flags: [],
    example: "\\w++:",
    source: "Java SE 25 Pattern documentation",
    sourceUrl: JAVA_REFERENCE_SOURCE,
  },
  {
    id: "java-linebreak",
    construct: "Unicode linebreak",
    syntax: "\\R",
    explanation:
      "Matches one Unicode linebreak sequence, including a CRLF pair as one sequence.",
    flavours: ["java"],
    flags: [],
    example: "^.+\\R.+$",
    source: "Java SE 25 Pattern documentation",
    sourceUrl: JAVA_REFERENCE_SOURCE,
  },
  {
    id: "java-grapheme",
    construct: "Extended grapheme cluster",
    syntax: "\\X",
    explanation:
      "Matches one extended Unicode grapheme cluster rather than one code point.",
    flavours: ["java"],
    flags: [],
    example: "\\X",
    source: "Java SE 25 Pattern documentation",
    sourceUrl: JAVA_REFERENCE_SOURCE,
  },
  {
    id: "java-unicode-property",
    construct: "Unicode property",
    syntax: "\\p{Property}",
    explanation:
      "Matches characters selected by a supported Unicode category, script, block or binary property.",
    flavours: ["java"],
    flags: ["U"],
    example: "\\p{IsLatin}+",
    caveat:
      "The bundled TeaVM adapter reports compatibility warnings where its Pattern implementation differs from the documented Java SE language.",
    source: "Java SE 25 Pattern documentation",
    sourceUrl: JAVA_REFERENCE_SOURCE,
  },
];

const PHP_REFERENCE_SOURCE =
  "https://www.php.net/manual/en/reference.pcre.pattern.syntax.php";

export const PHP_REFERENCE: readonly ReferenceEntry[] = [
  {
    id: "php-named-capture",
    construct: "Named capture",
    syntax: "(?<name>...)",
    explanation:
      "Captures under a number and name in PHP's PCRE2-backed preg functions.",
    flavours: ["php"],
    flags: [],
    example: "(?<year>\\d{4})",
    caveat:
      "The application owns pattern and flags separately; PHP delimiter handling is outside the lexical explanation tree.",
    source: "PHP PCRE pattern syntax",
    sourceUrl: PHP_REFERENCE_SOURCE,
  },
  {
    id: "php-branch-reset",
    construct: "Branch-reset group",
    syntax: "(?|...|...)",
    explanation: "Reuses capture numbers across alternatives.",
    flavours: ["php"],
    flags: [],
    example: "(?|(red)|(blue))-(\\d+)",
    caveat:
      "The partial lexical provider does not infer branch-reset capture numbers; PHP/PCRE2 execution is authoritative.",
    source: "PHP PCRE pattern syntax",
    sourceUrl: PHP_REFERENCE_SOURCE,
  },
  {
    id: "php-extended",
    construct: "Extended layout",
    syntax: "whitespace  # comment",
    explanation:
      "Ignores unescaped layout whitespace and enables comments outside character classes.",
    flavours: ["php"],
    flags: ["x"],
    example: "(?<year>\\d{4})  # year",
    source: "PHP PCRE pattern syntax",
    sourceUrl: PHP_REFERENCE_SOURCE,
  },
];

const PERL_REFERENCE_SOURCE = "https://perldoc.perl.org/5.28.1/perlre";

export const PERL_REFERENCE: readonly ReferenceEntry[] = [
  {
    id: "perl-named-capture",
    construct: "Named capture",
    syntax: "(?<name>...)",
    explanation:
      "Captures under a number and name; Perl 5.28 also accepts (?'name'...).",
    flavours: ["perl"],
    flags: [],
    example: "(?<year>\\d{4})",
    source: "Perl 5.28.1 perlre",
    sourceUrl: PERL_REFERENCE_SOURCE,
  },
  {
    id: "perl-recursion",
    construct: "Named subpattern call",
    syntax: "(?&name)",
    explanation: "Recursively invokes a named subpattern.",
    flavours: ["perl"],
    flags: [],
    example: "(?<pair>\\((?:[^()]|(?&pair))*\\))",
    caveat:
      "This profile intentionally targets legacy Perl 5.28.1 through WebPerl 0.09-beta, not current desktop Perl.",
    source: "Perl 5.28.1 perlre",
    sourceUrl: PERL_REFERENCE_SOURCE,
  },
  {
    id: "perl-character-rules",
    construct: "Character-set rules",
    syntax: "/a  /d  /l  /u",
    explanation:
      "Selects ASCII, default, locale or Unicode character-class behavior.",
    flavours: ["perl"],
    flags: ["a", "d", "l", "u"],
    example: "\\w+",
    caveat:
      "These character-set modifiers are mutually exclusive. Perl's two-character /aa modifier is intentionally unavailable through the current one-character worker flag protocol.",
    source: "Perl 5.28.1 perlre",
    sourceUrl: PERL_REFERENCE_SOURCE,
  },
];

const RUBY_REFERENCE_SOURCE = "https://docs.ruby-lang.org/en/4.0/Regexp.html";

export const RUBY_REFERENCE: readonly ReferenceEntry[] = [
  {
    id: "ruby-named-capture",
    construct: "Named capture",
    syntax: "(?<name>...)",
    explanation:
      "Captures under a name and number; Ruby also accepts (?'name'...).",
    flavours: ["ruby"],
    flags: [],
    example: "(?<year>\\d{4})",
    source: "Ruby 4.0 Regexp documentation",
    sourceUrl: RUBY_REFERENCE_SOURCE,
  },
  {
    id: "ruby-subexpression-call",
    construct: "Subexpression call",
    syntax: "\\g<name>",
    explanation: "Invokes the pattern of an earlier named group.",
    flavours: ["ruby"],
    flags: [],
    example: "(?<pair>\\((?:[^()]|\\g<pair>)*\\))",
    caveat:
      "This is an Onigmo pattern construct, not Ruby String#gsub replacement syntax.",
    source: "Ruby 4.0 Regexp documentation",
    sourceUrl: RUBY_REFERENCE_SOURCE,
  },
  {
    id: "ruby-atomic",
    construct: "Atomic group",
    syntax: "(?>...)",
    explanation: "Prevents later backtracking into the group.",
    flavours: ["ruby"],
    flags: [],
    example: "(?>\\d+)\\d",
    source: "Ruby 4.0 Regexp documentation",
    sourceUrl: RUBY_REFERENCE_SOURCE,
  },
];

const CPP_REFERENCE_SOURCE = "https://eel.is/c++draft/re.grammar";

export const CPP_REFERENCE: readonly ReferenceEntry[] = [
  {
    id: "cpp-grammar",
    construct: "Grammar selection",
    syntax: "ECMAScript | basic | extended | awk | grep | egrep",
    explanation:
      "Selects one standard std::regex grammar through syntax_option_type.",
    flavours: ["cpp"],
    flags: [],
    example: "(\\w+)",
    caveat:
      "The quick reference examples use the default ECMAScript grammar. Capture syntax differs in the POSIX-derived grammars.",
    source: "C++ regular-expression grammar",
    sourceUrl: CPP_REFERENCE_SOURCE,
  },
  {
    id: "cpp-capture",
    construct: "ECMAScript capture",
    syntax: "(...)",
    explanation:
      "Creates a marked subexpression under the default ECMAScript grammar.",
    flavours: ["cpp"],
    flags: ["n"],
    example: "(\\d{4})",
    caveat:
      "The n (nosubs) flag suppresses retained submatches; the partial provider omits captures when it is selected.",
    source: "C++ regular-expression grammar",
    sourceUrl: CPP_REFERENCE_SOURCE,
  },
  {
    id: "cpp-backreference",
    construct: "ECMAScript backreference",
    syntax: "\\1",
    explanation:
      "Matches text retained by a preceding marked subexpression in the ECMAScript grammar.",
    flavours: ["cpp"],
    flags: [],
    example: "(\\w+)\\s+\\1",
    source: "C++ regular-expression grammar",
    sourceUrl: CPP_REFERENCE_SOURCE,
  },
];

const GO_REFERENCE_SOURCE = "https://pkg.go.dev/regexp/syntax";

export const GO_REFERENCE: readonly ReferenceEntry[] = [
  {
    id: "go-named-capture",
    construct: "Named capture",
    syntax: "(?P<name>...)",
    explanation: "Creates a numbered subexpression with a name.",
    flavours: ["go"],
    flags: [],
    example: "(?P<year>\\d{4})",
    source: "Go regexp/syntax documentation",
    sourceUrl: GO_REFERENCE_SOURCE,
  },
  {
    id: "go-inline-flags",
    construct: "Scoped flags",
    syntax: "(?im-s:...)",
    explanation: "Enables and disables supported flags for one group.",
    flavours: ["go"],
    flags: ["i", "m", "s", "U"],
    example: "(?i:invoice)-(?-i:[A-Z]+)",
    source: "Go regexp/syntax documentation",
    sourceUrl: GO_REFERENCE_SOURCE,
  },
  {
    id: "go-re2-boundary",
    construct: "Linear-time syntax boundary",
    syntax: "(re)",
    explanation:
      "Go regexp uses RE2-style syntax and deliberately omits lookaround and backreferences.",
    flavours: ["go"],
    flags: [],
    example: "^(?:[A-Za-z]+|\\d+)$",
    caveat:
      "Unsupported constructs are rejected by the Go compiler, which remains authoritative.",
    source: "Go regexp/syntax documentation",
    sourceUrl: GO_REFERENCE_SOURCE,
  },
];

const RUST_REFERENCE_SOURCE = "https://docs.rs/regex/1.13.1/regex/";

export const RUST_REFERENCE: readonly ReferenceEntry[] = [
  {
    id: "rust-named-capture",
    construct: "Named capture",
    syntax: "(?<name>...)",
    explanation:
      "Creates a numbered capture with a name; (?P<name>...) is also accepted.",
    flavours: ["rust"],
    flags: [],
    example: "(?<year>\\d{4})",
    source: "Rust regex 1.13.1 documentation",
    sourceUrl: RUST_REFERENCE_SOURCE,
  },
  {
    id: "rust-inline-flags",
    construct: "Scoped flags",
    syntax: "(?imRsux-U:...)",
    explanation: "Changes supported matching modes within one group.",
    flavours: ["rust"],
    flags: ["i", "m", "R", "s", "U", "u", "x"],
    example: "(?i:invoice)-(?-i:[A-Z]+)",
    source: "Rust regex 1.13.1 documentation",
    sourceUrl: RUST_REFERENCE_SOURCE,
  },
  {
    id: "rust-set-operations",
    construct: "Character-class set operations",
    syntax: "[class&&class]",
    explanation:
      "Intersects, subtracts or symmetrically combines nested character classes.",
    flavours: ["rust"],
    flags: ["u"],
    example: "[\\p{Greek}&&\\pL]+",
    source: "Rust regex 1.13.1 documentation",
    sourceUrl: RUST_REFERENCE_SOURCE,
  },
];

const DOTNET_REFERENCE_SOURCE =
  "https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference";

export const DOTNET_REFERENCE: readonly ReferenceEntry[] = [
  {
    id: "dotnet-named-capture",
    construct: "Named capture",
    syntax: "(?<name>...)",
    explanation:
      "Captures under both a name and number; repeated groups can retain capture history.",
    flavours: ["dotnet"],
    flags: [],
    example: "(?<year>\\d{4})",
    source: ".NET regular-expression language reference",
    sourceUrl: DOTNET_REFERENCE_SOURCE,
  },
  {
    id: "dotnet-balancing-group",
    construct: "Balancing group",
    syntax: "(?<open-close>...)",
    explanation:
      "Subtracts one capture from another, enabling stack-like balancing patterns.",
    flavours: ["dotnet"],
    flags: [],
    example: "^(?'open'\\()+(?'-open'\\))+(?(open)(?!))$",
    caveat:
      "The partial lexical provider does not model balancing-group capture history.",
    source: ".NET regular-expression language reference",
    sourceUrl: DOTNET_REFERENCE_SOURCE,
  },
  {
    id: "dotnet-conditional",
    construct: "Conditional",
    syntax: "(?(name)yes|no)",
    explanation:
      "Selects a branch according to whether a named or numbered group participated.",
    flavours: ["dotnet"],
    flags: [],
    example: "(?<open><)?\\w+(?(open)>|$)",
    source: ".NET regular-expression language reference",
    sourceUrl: DOTNET_REFERENCE_SOURCE,
  },
];

export const SCALA_REFERENCE: readonly ReferenceEntry[] = [
  {
    ...JAVA_REFERENCE[0]!,
    id: "scala-named-capture",
    flavours: ["scala"],
    source: "Scala Regex / Java Pattern compatibility reference",
  },
  {
    ...JAVA_REFERENCE[2]!,
    id: "scala-class-intersection",
    flavours: ["scala"],
    source: "Scala Regex / Java Pattern compatibility reference",
  },
  {
    ...JAVA_REFERENCE[3]!,
    id: "scala-scoped-flags",
    flavours: ["scala"],
    caveat:
      "Scala/JVM regex syntax delegates to Java Pattern, while this browser profile executes TeaVM 0.15.0 compatibility behavior rather than an OpenJDK JVM.",
    source: "Scala Regex / Java Pattern compatibility reference",
  },
];

export interface FlavourReference {
  readonly label: string;
  readonly entries: readonly ReferenceEntry[];
  readonly note?: string;
}

export const REFERENCE_BY_FLAVOUR: Readonly<
  Record<RegexFlavourId, FlavourReference>
> = {
  ecmascript: {
    label: "JavaScript (ECMAScript)",
    entries: ECMASCRIPT_REFERENCE,
  },
  pcre2: {
    label: "PCRE2",
    entries: PCRE2_REFERENCE,
  },
  python: {
    label: "Python 3.14 re",
    entries: PYTHON_REFERENCE,
  },
  php: {
    label: "PHP 8.5.8 preg / PCRE2 10.44",
    entries: PHP_REFERENCE,
    note: "PHP's preg wrapper has delimiter, modifier, offset and replacement behavior beyond raw PCRE2. The partial provider does not relabel standalone PCRE2 results as PHP.",
  },
  perl: {
    label: "Perl 5.28.1 / WebPerl 0.09-beta",
    entries: PERL_REFERENCE,
    note: "This is an explicitly legacy WebPerl target. Embedded regex code is rejected, and replacement is a fixed data-only subset ($$, greedy $n and ${name}) rather than evaluated Perl interpolation.",
  },
  ruby: {
    label: "Ruby 4.0 Regexp",
    entries: RUBY_REFERENCE,
  },
  cpp: {
    label: "C++ libc++ std::regex",
    entries: CPP_REFERENCE,
    note: "Examples use the default ECMAScript grammar. The selected grammar option and libc++ runtime identity remain authoritative.",
  },
  go: {
    label: "Go 1.26 regexp",
    entries: GO_REFERENCE,
  },
  rust: {
    label: "Rust regex 1.13.1",
    entries: RUST_REFERENCE,
  },
  dotnet: {
    label: ".NET 10 Regex",
    entries: DOTNET_REFERENCE,
  },
  java: {
    label: "Java Pattern",
    entries: JAVA_REFERENCE,
    note: "This reference describes the Java Pattern language. The bundled TeaVM 0.15.0 adapter is a tested compatibility subset, not OpenJDK; replacement supports only single-digit $n references and not Java SE ${name}. Its diagnostics and engine metadata are authoritative for this build.",
  },
  pcre: {
    label: "PCRE",
    entries: [],
  },
  scala: {
    label: "Scala Regex / Java compatibility",
    entries: SCALA_REFERENCE,
    note: "Scala's JVM regex syntax is represented as a Java Pattern compatibility profile. The shared TeaVM 0.15.0 runtime is not a Scala VM or OpenJDK.",
  },
};
