import { Position as h } from "../../../../../vscode-languageserver-types@3.17.5/node_modules/vscode-languageserver-types/lib/esm/main.js";
import { tokenToRange as a } from "../utils/cst-utils.js";
class p {
  constructor() {
    this.nodeStack = [];
  }
  get current() {
    var t;
    return (t = this.nodeStack[this.nodeStack.length - 1]) !== null && t !== void 0 ? t : this.rootNode;
  }
  buildRootNode(t) {
    return this.rootNode = new f(t), this.rootNode.root = this.rootNode, this.nodeStack = [this.rootNode], this.rootNode;
  }
  buildCompositeNode(t) {
    const e = new l();
    return e.grammarSource = t, e.root = this.rootNode, this.current.content.push(e), this.nodeStack.push(e), e;
  }
  buildLeafNode(t, e) {
    const n = new c(t.startOffset, t.image.length, a(t), t.tokenType, !e);
    return n.grammarSource = e, n.root = this.rootNode, this.current.content.push(n), n;
  }
  removeNode(t) {
    const e = t.container;
    if (e) {
      const n = e.content.indexOf(t);
      n >= 0 && e.content.splice(n, 1);
    }
  }
  addHiddenNodes(t) {
    const e = [];
    for (const o of t) {
      const d = new c(o.startOffset, o.image.length, a(o), o.tokenType, !0);
      d.root = this.rootNode, e.push(d);
    }
    let n = this.current, s = !1;
    if (n.content.length > 0) {
      n.content.push(...e);
      return;
    }
    for (; n.container; ) {
      const o = n.container.content.indexOf(n);
      if (o > 0) {
        n.container.content.splice(o, 0, ...e), s = !0;
        break;
      }
      n = n.container;
    }
    s || this.rootNode.content.unshift(...e);
  }
  construct(t) {
    const e = this.current;
    typeof t.$type == "string" && (this.current.astNode = t), t.$cstNode = e;
    const n = this.nodeStack.pop();
    (n == null ? void 0 : n.content.length) === 0 && this.removeNode(n);
  }
}
class u {
  /** @deprecated use `container` instead. */
  get parent() {
    return this.container;
  }
  /** @deprecated use `grammarSource` instead. */
  get feature() {
    return this.grammarSource;
  }
  get hidden() {
    return !1;
  }
  get astNode() {
    var t, e;
    const n = typeof ((t = this._astNode) === null || t === void 0 ? void 0 : t.$type) == "string" ? this._astNode : (e = this.container) === null || e === void 0 ? void 0 : e.astNode;
    if (!n)
      throw new Error("This node has no associated AST element");
    return n;
  }
  set astNode(t) {
    this._astNode = t;
  }
  /** @deprecated use `astNode` instead. */
  get element() {
    return this.astNode;
  }
  get text() {
    return this.root.fullText.substring(this.offset, this.end);
  }
}
class c extends u {
  get offset() {
    return this._offset;
  }
  get length() {
    return this._length;
  }
  get end() {
    return this._offset + this._length;
  }
  get hidden() {
    return this._hidden;
  }
  get tokenType() {
    return this._tokenType;
  }
  get range() {
    return this._range;
  }
  constructor(t, e, n, s, o = !1) {
    super(), this._hidden = o, this._offset = t, this._tokenType = s, this._length = e, this._range = n;
  }
}
class l extends u {
  constructor() {
    super(...arguments), this.content = new i(this);
  }
  /** @deprecated use `content` instead. */
  get children() {
    return this.content;
  }
  get offset() {
    var t, e;
    return (e = (t = this.firstNonHiddenNode) === null || t === void 0 ? void 0 : t.offset) !== null && e !== void 0 ? e : 0;
  }
  get length() {
    return this.end - this.offset;
  }
  get end() {
    var t, e;
    return (e = (t = this.lastNonHiddenNode) === null || t === void 0 ? void 0 : t.end) !== null && e !== void 0 ? e : 0;
  }
  get range() {
    const t = this.firstNonHiddenNode, e = this.lastNonHiddenNode;
    if (t && e) {
      if (this._rangeCache === void 0) {
        const { range: n } = t, { range: s } = e;
        this._rangeCache = { start: n.start, end: s.end.line < n.start.line ? n.start : s.end };
      }
      return this._rangeCache;
    } else
      return { start: h.create(0, 0), end: h.create(0, 0) };
  }
  get firstNonHiddenNode() {
    for (const t of this.content)
      if (!t.hidden)
        return t;
    return this.content[0];
  }
  get lastNonHiddenNode() {
    for (let t = this.content.length - 1; t >= 0; t--) {
      const e = this.content[t];
      if (!e.hidden)
        return e;
    }
    return this.content[this.content.length - 1];
  }
}
class i extends Array {
  constructor(t) {
    super(), this.parent = t, Object.setPrototypeOf(this, i.prototype);
  }
  push(...t) {
    return this.addParents(t), super.push(...t);
  }
  unshift(...t) {
    return this.addParents(t), super.unshift(...t);
  }
  splice(t, e, ...n) {
    return this.addParents(n), super.splice(t, e, ...n);
  }
  addParents(t) {
    for (const e of t)
      e.container = this.parent;
  }
}
class f extends l {
  get text() {
    return this._text.substring(this.offset, this.end);
  }
  get fullText() {
    return this._text;
  }
  constructor(t) {
    super(), this._text = "", this._text = t ?? "";
  }
}
export {
  u as AbstractCstNode,
  l as CompositeCstNodeImpl,
  p as CstNodeBuilder,
  c as LeafCstNodeImpl,
  f as RootCstNodeImpl
};
