import { tokenize as L } from "../tokenizer/tokenize.js";
import { r as g, getOrInsert as $, throwIfNullish as b, PosixClassNames as N, cpOf as S } from "../utils.js";
import { isQuantifiable as V } from "./node-utils.js";
import { hasOnlyChild as le } from "./node-utils.js";
function ce(e, n = {}) {
  const t = { flags: "", normalizeUnknownPropertyNames: !1, skipBackrefValidation: !1, skipLookbehindValidation: !1, skipPropertyNameValidation: !1, unicodePropertyMap: null, ...n, rules: { captureGroup: !1, singleline: !1, ...n.rules } }, r = L(e, { flags: t.flags, rules: { captureGroup: t.rules.captureGroup, singleline: t.rules.singleline } }), i = (d, f) => {
    const c = r.tokens[a.nextIndex];
    switch (a.parent = d, a.nextIndex++, c.type) {
      case "Alternator":
        return m();
      case "Assertion":
        return U(c);
      case "Backreference":
        return B(c, a);
      case "Character":
        return P(c.value, { useLastValid: !!f.isCheckingRangeEnd });
      case "CharacterClassHyphen":
        return z(c, a, f);
      case "CharacterClassOpen":
        return R(c, a, f);
      case "CharacterSet":
        return M(c, a);
      case "Directive":
        return Y(c.kind, { flags: c.flags });
      case "GroupOpen":
        return O(c, a, f);
      case "NamedCallout":
        return T(c.kind, c.tag, c.arguments);
      case "Quantifier":
        return F(c, a);
      case "Subroutine":
        return Q(c, a);
      default:
        throw new Error(`Unexpected token type "${c.type}"`);
    }
  }, a = { capturingGroups: [], hasNumberedRef: !1, namedGroupsByName: /* @__PURE__ */ new Map(), nextIndex: 0, normalizeUnknownPropertyNames: t.normalizeUnknownPropertyNames, parent: null, skipBackrefValidation: t.skipBackrefValidation, skipLookbehindValidation: t.skipLookbehindValidation, skipPropertyNameValidation: t.skipPropertyNameValidation, subroutines: [], tokens: r.tokens, unicodePropertyMap: t.unicodePropertyMap, walk: i }, o = ee(H(r.flags));
  let u = o.body[0];
  for (; a.nextIndex < r.tokens.length; ) {
    const d = i(u, {});
    d.type === "Alternative" ? (o.body.push(d), u = d) : u.body.push(d);
  }
  const { capturingGroups: s, hasNumberedRef: p, namedGroupsByName: l, subroutines: h } = a;
  if (p && l.size && !t.rules.captureGroup) throw new Error("Numbered backref/subroutine not allowed when using named capture");
  for (const { ref: d } of h) if (typeof d == "number") {
    if (d > s.length) throw new Error("Subroutine uses a group number that's not defined");
    d && (s[d - 1].isSubroutined = !0);
  } else if (l.has(d)) {
    if (l.get(d).length > 1) throw new Error(g`Subroutine uses a duplicate group name "\g<${d}>"`);
    l.get(d)[0].isSubroutined = !0;
  } else throw new Error(g`Subroutine uses a group name that's not defined "\g<${d}>"`);
  return o;
}
function U({ kind: e }) {
  return Z(b({ "^": "line_start", $: "line_end", "\\A": "string_start", "\\b": "word_boundary", "\\B": "word_boundary", "\\G": "search_start", "\\y": "text_segment_boundary", "\\Y": "text_segment_boundary", "\\z": "string_end", "\\Z": "string_end_newline" }[e], `Unexpected assertion kind "${e}"`), { negate: e === g`\B` || e === g`\Y` });
}
function B({ raw: e }, n) {
  const t = /^\\k[<']/.test(e), r = t ? e.slice(3, -1) : e.slice(1), i = (a, o = !1) => {
    const u = n.capturingGroups.length;
    let s = !1;
    if (a > u) if (n.skipBackrefValidation) s = !0;
    else throw new Error(`Not enough capturing groups defined to the left "${e}"`);
    return n.hasNumberedRef = !0, C(o ? u + 1 - a : a, { orphan: s });
  };
  if (t) {
    const a = /^(?<sign>-?)0*(?<num>[1-9]\d*)$/.exec(r);
    if (a) return i(+a.groups.num, !!a.groups.sign);
    if (/[-+]/.test(r)) throw new Error(`Invalid backref name "${e}"`);
    if (!n.namedGroupsByName.has(r)) throw new Error(`Group name not defined to the left "${e}"`);
    return C(r);
  }
  return i(+r);
}
function z(e, n, t) {
  const { tokens: r, walk: i } = n, a = n.parent, o = a.body.at(-1), u = r[n.nextIndex];
  if (!t.isCheckingRangeEnd && o && o.type !== "CharacterClass" && o.type !== "CharacterClassRange" && u && u.type !== "CharacterClassOpen" && u.type !== "CharacterClassClose" && u.type !== "CharacterClassIntersector") {
    const s = i(a, { ...t, isCheckingRangeEnd: !0 });
    if (o.type === "Character" && s.type === "Character") return a.body.pop(), J(o, s);
    throw new Error("Invalid character class range");
  }
  return P(S("-"));
}
function R({ negate: e }, n, t) {
  const { tokens: r, walk: i } = n, a = r[n.nextIndex], o = [k()];
  let u = A(a);
  for (; u.type !== "CharacterClassClose"; ) {
    if (u.type === "CharacterClassIntersector") o.push(k()), n.nextIndex++;
    else {
      const p = o.at(-1);
      p.body.push(i(p, t));
    }
    u = A(r[n.nextIndex], a);
  }
  const s = k({ negate: e });
  return o.length === 1 ? s.body = o[0].body : (s.kind = "intersection", s.body = o.map((p) => p.body.length === 1 ? p.body[0] : p)), n.nextIndex++, s;
}
function M({ kind: e, negate: n, value: t }, r) {
  const { normalizeUnknownPropertyNames: i, skipPropertyNameValidation: a, unicodePropertyMap: o } = r;
  if (e === "property") {
    const u = _(t);
    if (N.has(u) && !(o != null && o.has(u))) e = "posix", t = u;
    else return te(t, { negate: n, normalizeUnknownPropertyNames: i, skipPropertyNameValidation: a, unicodePropertyMap: o });
  }
  return e === "posix" ? W(t, { negate: n }) : X(e, { negate: n });
}
function O(e, n, t) {
  const { tokens: r, capturingGroups: i, namedGroupsByName: a, skipLookbehindValidation: o, walk: u } = n, s = re(e), p = s.type === "AbsenceFunction", l = I(s), h = l && s.negate;
  if (s.type === "CapturingGroup" && (i.push(s), s.name && $(a, s.name, []).push(s)), p && t.isInAbsenceFunction) throw new Error("Nested absence function not supported by Oniguruma");
  let d = E(r[n.nextIndex]);
  for (; d.type !== "GroupClose"; ) {
    if (d.type === "Alternator") s.body.push(m()), n.nextIndex++;
    else {
      const f = s.body.at(-1), c = u(f, { ...t, isInAbsenceFunction: t.isInAbsenceFunction || p, isInLookbehind: t.isInLookbehind || l, isInNegLookbehind: t.isInNegLookbehind || h });
      if (f.body.push(c), (l || t.isInLookbehind) && !o) {
        const w = "Lookbehind includes a pattern not allowed by Oniguruma";
        if (h || t.isInNegLookbehind) {
          if (v(c) || c.type === "CapturingGroup") throw new Error(w);
        } else if (v(c) || I(c) && c.negate) throw new Error(w);
      }
    }
    d = E(r[n.nextIndex]);
  }
  return n.nextIndex++, s;
}
function F({ kind: e, min: n, max: t }, r) {
  const i = r.parent, a = i.body.at(-1);
  if (!a || !V(a)) throw new Error("Quantifier requires a repeatable token");
  const o = j(e, n, t, a);
  return i.body.pop(), o;
}
function Q({ raw: e }, n) {
  const { capturingGroups: t, subroutines: r } = n;
  let i = e.slice(3, -1);
  const a = /^(?<sign>[-+]?)0*(?<num>[1-9]\d*)$/.exec(i);
  if (a) {
    const u = +a.groups.num, s = t.length;
    if (n.hasNumberedRef = !0, i = { "": u, "+": s + u, "-": s + 1 - u }[a.groups.sign], i < 1) throw new Error("Invalid subroutine number");
  } else i === "0" && (i = 0);
  const o = ne(i);
  return r.push(o), o;
}
function D(e, n) {
  return { type: "AbsenceFunction", kind: e, body: y(n == null ? void 0 : n.body) };
}
function m(e) {
  return { type: "Alternative", body: G(e == null ? void 0 : e.body) };
}
function Z(e, n) {
  const t = { type: "Assertion", kind: e };
  return (e === "word_boundary" || e === "text_segment_boundary") && (t.negate = !!(n != null && n.negate)), t;
}
function C(e, n) {
  const t = !!(n != null && n.orphan);
  return { type: "Backreference", ref: e, ...t && { orphan: t } };
}
function q(e, n) {
  const t = { name: void 0, isSubroutined: !1, ...n };
  if (t.name !== void 0 && !ae(t.name)) throw new Error(`Group name "${t.name}" invalid in Oniguruma`);
  return { type: "CapturingGroup", number: e, ...t.name && { name: t.name }, ...t.isSubroutined && { isSubroutined: t.isSubroutined }, body: y(n == null ? void 0 : n.body) };
}
function P(e, n) {
  const t = { useLastValid: !1, ...n };
  if (e > 1114111) {
    const r = e.toString(16);
    if (t.useLastValid) e = 1114111;
    else throw e > 1310719 ? new Error(`Invalid code point out of range "\\x{${r}}"`) : new Error(`Invalid code point out of range in JS "\\x{${r}}"`);
  }
  return { type: "Character", value: e };
}
function k(e) {
  const n = { kind: "union", negate: !1, ...e };
  return { type: "CharacterClass", kind: n.kind, negate: n.negate, body: G(e == null ? void 0 : e.body) };
}
function J(e, n) {
  if (n.value < e.value) throw new Error("Character class range out of order");
  return { type: "CharacterClassRange", min: e, max: n };
}
function X(e, n) {
  const t = !!(n != null && n.negate), r = { type: "CharacterSet", kind: e };
  return (e === "digit" || e === "hex" || e === "newline" || e === "space" || e === "word") && (r.negate = t), (e === "text_segment" || e === "newline" && !t) && (r.variableLength = !0), r;
}
function Y(e, n = {}) {
  if (e === "keep") return { type: "Directive", kind: e };
  if (e === "flags") return { type: "Directive", kind: e, flags: b(n.flags) };
  throw new Error(`Unexpected directive kind "${e}"`);
}
function H(e) {
  return { type: "Flags", ...e };
}
function x(e) {
  const n = e == null ? void 0 : e.atomic, t = e == null ? void 0 : e.flags;
  if (n && t) throw new Error("Atomic group cannot have flags");
  return { type: "Group", ...n && { atomic: n }, ...t && { flags: t }, body: y(e == null ? void 0 : e.body) };
}
function K(e) {
  const n = { behind: !1, negate: !1, ...e };
  return { type: "LookaroundAssertion", kind: n.behind ? "lookbehind" : "lookahead", negate: n.negate, body: y(e == null ? void 0 : e.body) };
}
function T(e, n, t) {
  return { type: "NamedCallout", kind: e, tag: n, arguments: t };
}
function W(e, n) {
  const t = !!(n != null && n.negate);
  if (!N.has(e)) throw new Error(`Invalid POSIX class "${e}"`);
  return { type: "CharacterSet", kind: "posix", value: e, negate: t };
}
function j(e, n, t, r) {
  if (n > t) throw new Error("Invalid reversed quantifier range");
  return { type: "Quantifier", kind: e, min: n, max: t, body: r };
}
function ee(e, n) {
  return { type: "Regex", body: y(n == null ? void 0 : n.body), flags: e };
}
function ne(e) {
  return { type: "Subroutine", ref: e };
}
function te(e, n) {
  var i;
  const t = { negate: !1, normalizeUnknownPropertyNames: !1, skipPropertyNameValidation: !1, unicodePropertyMap: null, ...n };
  let r = (i = t.unicodePropertyMap) == null ? void 0 : i.get(_(e));
  if (!r) {
    if (t.normalizeUnknownPropertyNames) r = oe(e);
    else if (t.unicodePropertyMap && !t.skipPropertyNameValidation) throw new Error(g`Invalid Unicode property "\p{${e}}"`);
  }
  return { type: "CharacterSet", kind: "property", value: r ?? e, negate: t.negate };
}
function re({ flags: e, kind: n, name: t, negate: r, number: i }) {
  switch (n) {
    case "absence_repeater":
      return D("repeater");
    case "atomic":
      return x({ atomic: !0 });
    case "capturing":
      return q(i, { name: t });
    case "group":
      return x({ flags: e });
    case "lookahead":
    case "lookbehind":
      return K({ behind: n === "lookbehind", negate: r });
    default:
      throw new Error(`Unexpected group kind "${n}"`);
  }
}
function y(e) {
  if (e === void 0) e = [m()];
  else if (!Array.isArray(e) || !e.length || !e.every((n) => n.type === "Alternative")) throw new Error("Invalid body; expected array of one or more Alternative nodes");
  return e;
}
function G(e) {
  if (e === void 0) e = [];
  else if (!Array.isArray(e) || !e.every((n) => !!n.type)) throw new Error("Invalid body; expected array of nodes");
  return e;
}
function v(e) {
  return e.type === "LookaroundAssertion" && e.kind === "lookahead";
}
function I(e) {
  return e.type === "LookaroundAssertion" && e.kind === "lookbehind";
}
function ae(e) {
  return /^[\p{Alpha}\p{Pc}][^)]*$/u.test(e);
}
function oe(e) {
  return e.trim().replace(/[- _]+/g, "_").replace(/[A-Z][a-z]+(?=[A-Z])/g, "$&_").replace(/[A-Za-z]+/g, (n) => n[0].toUpperCase() + n.slice(1).toLowerCase());
}
function _(e) {
  return e.replace(/[- _]+/g, "").toLowerCase();
}
function A(e, n) {
  return b(e, `${(n == null ? void 0 : n.type) === "Character" && n.value === 93 ? "Empty" : "Unclosed"} character class`);
}
function E(e) {
  return b(e, "Unclosed group");
}
export {
  D as createAbsenceFunction,
  m as createAlternative,
  Z as createAssertion,
  C as createBackreference,
  q as createCapturingGroup,
  P as createCharacter,
  k as createCharacterClass,
  J as createCharacterClassRange,
  X as createCharacterSet,
  Y as createDirective,
  H as createFlags,
  x as createGroup,
  K as createLookaroundAssertion,
  T as createNamedCallout,
  W as createPosixClass,
  j as createQuantifier,
  ee as createRegex,
  ne as createSubroutine,
  te as createUnicodeProperty,
  le as hasOnlyChild,
  V as isQuantifiable,
  ce as parse,
  _ as slug
};
