import { throwIfNullish as S } from "../utils.js";
function F(o, v, b = null) {
  function m(e, l) {
    for (let r = 0; r < e.length; r++) {
      const t = s(e[r], l, r, e);
      r = Math.max(-1, r + t);
    }
  }
  function s(e, l = null, r = null, t = null) {
    var w, A;
    let i = 0, f = !1;
    const p = { node: e, parent: l, key: r, container: t, root: o, remove() {
      x(t).splice(Math.max(0, u(r) + i), 1), i--, f = !0;
    }, removeAllNextSiblings() {
      return x(t).splice(u(r) + 1);
    }, removeAllPrevSiblings() {
      const a = u(r) + i;
      return i -= a, x(t).splice(0, Math.max(0, a));
    }, replaceWith(a, k = {}) {
      const C = !!k.traverse;
      t ? t[Math.max(0, u(r) + i)] = a : S(l, "Can't replace root node")[r] = a, C && s(a, l, r, t), f = !0;
    }, replaceWithMultiple(a, k = {}) {
      const C = !!k.traverse;
      if (x(t).splice(Math.max(0, u(r) + i), 1, ...a), i += a.length - 1, C) {
        let M = 0;
        for (let d = 0; d < a.length; d++) M += s(a[d], l, u(r) + d + M, t);
      }
      f = !0;
    }, skip() {
      f = !0;
    } }, { type: h } = e, n = v["*"], c = v[h], y = typeof n == "function" ? n : n == null ? void 0 : n.enter, g = typeof c == "function" ? c : c == null ? void 0 : c.enter;
    if (y == null || y(p, b), g == null || g(p, b), !f) switch (h) {
      case "AbsenceFunction":
      case "CapturingGroup":
      case "Group":
        m(e.body, e);
        break;
      case "Alternative":
      case "CharacterClass":
        m(e.body, e);
        break;
      case "Assertion":
      case "Backreference":
      case "Character":
      case "CharacterSet":
      case "Directive":
      case "Flags":
      case "NamedCallout":
      case "Subroutine":
        break;
      case "CharacterClassRange":
        s(e.min, e, "min"), s(e.max, e, "max");
        break;
      case "LookaroundAssertion":
        m(e.body, e);
        break;
      case "Quantifier":
        s(e.body, e, "body");
        break;
      case "Regex":
        m(e.body, e), s(e.flags, e, "flags");
        break;
      default:
        throw new Error(`Unexpected node type "${h}"`);
    }
    return (w = c == null ? void 0 : c.exit) == null || w.call(c, p, b), (A = n == null ? void 0 : n.exit) == null || A.call(n, p, b), i;
  }
  return s(o), o;
}
function x(o) {
  if (!Array.isArray(o)) throw new Error("Container expected");
  return o;
}
function u(o) {
  if (typeof o != "number") throw new Error("Numeric key expected");
  return o;
}
export {
  F as traverse
};
