import S, { QuoteType as u } from "./index-Tokenizer.js";
import "./index-decode.js";
import { fromCodePoint as p } from "./index-decode_codepoint.js";
const f = /* @__PURE__ */ new Set([
  "input",
  "option",
  "optgroup",
  "select",
  "button",
  "datalist",
  "textarea"
]), n = /* @__PURE__ */ new Set(["p"]), v = /* @__PURE__ */ new Set(["thead", "tbody"]), w = /* @__PURE__ */ new Set(["dd", "dt"]), x = /* @__PURE__ */ new Set(["rt", "rp"]), C = /* @__PURE__ */ new Map([
  ["tr", /* @__PURE__ */ new Set(["tr", "th", "td"])],
  ["th", /* @__PURE__ */ new Set(["th"])],
  ["td", /* @__PURE__ */ new Set(["thead", "th", "td"])],
  ["body", /* @__PURE__ */ new Set(["head", "link", "script"])],
  ["li", /* @__PURE__ */ new Set(["li"])],
  ["p", n],
  ["h1", n],
  ["h2", n],
  ["h3", n],
  ["h4", n],
  ["h5", n],
  ["h6", n],
  ["select", f],
  ["input", f],
  ["output", f],
  ["button", f],
  ["datalist", f],
  ["textarea", f],
  ["option", /* @__PURE__ */ new Set(["option"])],
  ["optgroup", /* @__PURE__ */ new Set(["optgroup", "option"])],
  ["dd", w],
  ["dt", w],
  ["address", n],
  ["article", n],
  ["aside", n],
  ["blockquote", n],
  ["details", n],
  ["div", n],
  ["dl", n],
  ["fieldset", n],
  ["figcaption", n],
  ["figure", n],
  ["footer", n],
  ["form", n],
  ["header", n],
  ["hr", n],
  ["main", n],
  ["nav", n],
  ["ol", n],
  ["pre", n],
  ["section", n],
  ["table", n],
  ["ul", n],
  ["rt", x],
  ["rp", x],
  ["tbody", v],
  ["tfoot", v]
]), T = /* @__PURE__ */ new Set([
  "area",
  "base",
  "basefont",
  "br",
  "col",
  "command",
  "embed",
  "frame",
  "hr",
  "img",
  "input",
  "isindex",
  "keygen",
  "link",
  "meta",
  "param",
  "source",
  "track",
  "wbr"
]), _ = /* @__PURE__ */ new Set(["math", "svg"]), k = /* @__PURE__ */ new Set([
  "mi",
  "mo",
  "mn",
  "ms",
  "mtext",
  "annotation-xml",
  "foreignobject",
  "desc",
  "title"
]), I = /\s|\//;
class y {
  constructor(t, e = {}) {
    var s, i, o, h, a;
    this.options = e, this.startIndex = 0, this.endIndex = 0, this.openTagStart = 0, this.tagname = "", this.attribname = "", this.attribvalue = "", this.attribs = null, this.stack = [], this.foreignContext = [], this.buffers = [], this.bufferOffset = 0, this.writeIndex = 0, this.ended = !1, this.cbs = t ?? {}, this.lowerCaseTagNames = (s = e.lowerCaseTags) !== null && s !== void 0 ? s : !e.xmlMode, this.lowerCaseAttributeNames = (i = e.lowerCaseAttributeNames) !== null && i !== void 0 ? i : !e.xmlMode, this.tokenizer = new ((o = e.Tokenizer) !== null && o !== void 0 ? o : S)(this.options, this), (a = (h = this.cbs).onparserinit) === null || a === void 0 || a.call(h, this);
  }
  // Tokenizer event handlers
  /** @internal */
  ontext(t, e) {
    var s, i;
    const o = this.getSlice(t, e);
    this.endIndex = e - 1, (i = (s = this.cbs).ontext) === null || i === void 0 || i.call(s, o), this.startIndex = e;
  }
  /** @internal */
  ontextentity(t) {
    var e, s;
    const i = this.tokenizer.getSectionStart();
    this.endIndex = i - 1, (s = (e = this.cbs).ontext) === null || s === void 0 || s.call(e, p(t)), this.startIndex = i;
  }
  isVoidElement(t) {
    return !this.options.xmlMode && T.has(t);
  }
  /** @internal */
  onopentagname(t, e) {
    this.endIndex = e;
    let s = this.getSlice(t, e);
    this.lowerCaseTagNames && (s = s.toLowerCase()), this.emitOpenTag(s);
  }
  emitOpenTag(t) {
    var e, s, i, o;
    this.openTagStart = this.startIndex, this.tagname = t;
    const h = !this.options.xmlMode && C.get(t);
    if (h)
      for (; this.stack.length > 0 && h.has(this.stack[this.stack.length - 1]); ) {
        const a = this.stack.pop();
        (s = (e = this.cbs).onclosetag) === null || s === void 0 || s.call(e, a, !0);
      }
    this.isVoidElement(t) || (this.stack.push(t), _.has(t) ? this.foreignContext.push(!0) : k.has(t) && this.foreignContext.push(!1)), (o = (i = this.cbs).onopentagname) === null || o === void 0 || o.call(i, t), this.cbs.onopentag && (this.attribs = {});
  }
  endOpenTag(t) {
    var e, s;
    this.startIndex = this.openTagStart, this.attribs && ((s = (e = this.cbs).onopentag) === null || s === void 0 || s.call(e, this.tagname, this.attribs, t), this.attribs = null), this.cbs.onclosetag && this.isVoidElement(this.tagname) && this.cbs.onclosetag(this.tagname, !0), this.tagname = "";
  }
  /** @internal */
  onopentagend(t) {
    this.endIndex = t, this.endOpenTag(!1), this.startIndex = t + 1;
  }
  /** @internal */
  onclosetag(t, e) {
    var s, i, o, h, a, l;
    this.endIndex = e;
    let r = this.getSlice(t, e);
    if (this.lowerCaseTagNames && (r = r.toLowerCase()), (_.has(r) || k.has(r)) && this.foreignContext.pop(), this.isVoidElement(r))
      !this.options.xmlMode && r === "br" && ((i = (s = this.cbs).onopentagname) === null || i === void 0 || i.call(s, "br"), (h = (o = this.cbs).onopentag) === null || h === void 0 || h.call(o, "br", {}, !0), (l = (a = this.cbs).onclosetag) === null || l === void 0 || l.call(a, "br", !1));
    else {
      const c = this.stack.lastIndexOf(r);
      if (c !== -1)
        if (this.cbs.onclosetag) {
          let d = this.stack.length - c;
          for (; d--; )
            this.cbs.onclosetag(this.stack.pop(), d !== 0);
        } else
          this.stack.length = c;
      else !this.options.xmlMode && r === "p" && (this.emitOpenTag("p"), this.closeCurrentTag(!0));
    }
    this.startIndex = e + 1;
  }
  /** @internal */
  onselfclosingtag(t) {
    this.endIndex = t, this.options.xmlMode || this.options.recognizeSelfClosing || this.foreignContext[this.foreignContext.length - 1] ? (this.closeCurrentTag(!1), this.startIndex = t + 1) : this.onopentagend(t);
  }
  closeCurrentTag(t) {
    var e, s;
    const i = this.tagname;
    this.endOpenTag(t), this.stack[this.stack.length - 1] === i && ((s = (e = this.cbs).onclosetag) === null || s === void 0 || s.call(e, i, !t), this.stack.pop());
  }
  /** @internal */
  onattribname(t, e) {
    this.startIndex = t;
    const s = this.getSlice(t, e);
    this.attribname = this.lowerCaseAttributeNames ? s.toLowerCase() : s;
  }
  /** @internal */
  onattribdata(t, e) {
    this.attribvalue += this.getSlice(t, e);
  }
  /** @internal */
  onattribentity(t) {
    this.attribvalue += p(t);
  }
  /** @internal */
  onattribend(t, e) {
    var s, i;
    this.endIndex = e, (i = (s = this.cbs).onattribute) === null || i === void 0 || i.call(s, this.attribname, this.attribvalue, t === u.Double ? '"' : t === u.Single ? "'" : t === u.NoValue ? void 0 : null), this.attribs && !Object.prototype.hasOwnProperty.call(this.attribs, this.attribname) && (this.attribs[this.attribname] = this.attribvalue), this.attribvalue = "";
  }
  getInstructionName(t) {
    const e = t.search(I);
    let s = e < 0 ? t : t.substr(0, e);
    return this.lowerCaseTagNames && (s = s.toLowerCase()), s;
  }
  /** @internal */
  ondeclaration(t, e) {
    this.endIndex = e;
    const s = this.getSlice(t, e);
    if (this.cbs.onprocessinginstruction) {
      const i = this.getInstructionName(s);
      this.cbs.onprocessinginstruction(`!${i}`, `!${s}`);
    }
    this.startIndex = e + 1;
  }
  /** @internal */
  onprocessinginstruction(t, e) {
    this.endIndex = e;
    const s = this.getSlice(t, e);
    if (this.cbs.onprocessinginstruction) {
      const i = this.getInstructionName(s);
      this.cbs.onprocessinginstruction(`?${i}`, `?${s}`);
    }
    this.startIndex = e + 1;
  }
  /** @internal */
  oncomment(t, e, s) {
    var i, o, h, a;
    this.endIndex = e, (o = (i = this.cbs).oncomment) === null || o === void 0 || o.call(i, this.getSlice(t, e - s)), (a = (h = this.cbs).oncommentend) === null || a === void 0 || a.call(h), this.startIndex = e + 1;
  }
  /** @internal */
  oncdata(t, e, s) {
    var i, o, h, a, l, r, c, d, g, b;
    this.endIndex = e;
    const m = this.getSlice(t, e - s);
    this.options.xmlMode || this.options.recognizeCDATA ? ((o = (i = this.cbs).oncdatastart) === null || o === void 0 || o.call(i), (a = (h = this.cbs).ontext) === null || a === void 0 || a.call(h, m), (r = (l = this.cbs).oncdataend) === null || r === void 0 || r.call(l)) : ((d = (c = this.cbs).oncomment) === null || d === void 0 || d.call(c, `[CDATA[${m}]]`), (b = (g = this.cbs).oncommentend) === null || b === void 0 || b.call(g)), this.startIndex = e + 1;
  }
  /** @internal */
  onend() {
    var t, e;
    if (this.cbs.onclosetag) {
      this.endIndex = this.startIndex;
      for (let s = this.stack.length; s > 0; this.cbs.onclosetag(this.stack[--s], !0))
        ;
    }
    (e = (t = this.cbs).onend) === null || e === void 0 || e.call(t);
  }
  /**
   * Resets the parser to a blank state, ready to parse a new HTML document
   */
  reset() {
    var t, e, s, i;
    (e = (t = this.cbs).onreset) === null || e === void 0 || e.call(t), this.tokenizer.reset(), this.tagname = "", this.attribname = "", this.attribs = null, this.stack.length = 0, this.startIndex = 0, this.endIndex = 0, (i = (s = this.cbs).onparserinit) === null || i === void 0 || i.call(s, this), this.buffers.length = 0, this.bufferOffset = 0, this.writeIndex = 0, this.ended = !1;
  }
  /**
   * Resets the parser, then parses a complete document and
   * pushes it to the handler.
   *
   * @param data Document to parse.
   */
  parseComplete(t) {
    this.reset(), this.end(t);
  }
  getSlice(t, e) {
    for (; t - this.bufferOffset >= this.buffers[0].length; )
      this.shiftBuffer();
    let s = this.buffers[0].slice(t - this.bufferOffset, e - this.bufferOffset);
    for (; e - this.bufferOffset > this.buffers[0].length; )
      this.shiftBuffer(), s += this.buffers[0].slice(0, e - this.bufferOffset);
    return s;
  }
  shiftBuffer() {
    this.bufferOffset += this.buffers[0].length, this.writeIndex--, this.buffers.shift();
  }
  /**
   * Parses a chunk of data and calls the corresponding callbacks.
   *
   * @param chunk Chunk to parse.
   */
  write(t) {
    var e, s;
    if (this.ended) {
      (s = (e = this.cbs).onerror) === null || s === void 0 || s.call(e, new Error(".write() after done!"));
      return;
    }
    this.buffers.push(t), this.tokenizer.running && (this.tokenizer.write(t), this.writeIndex++);
  }
  /**
   * Parses the end of the buffer and clears the stack, calls onend.
   *
   * @param chunk Optional final chunk to parse.
   */
  end(t) {
    var e, s;
    if (this.ended) {
      (s = (e = this.cbs).onerror) === null || s === void 0 || s.call(e, new Error(".end() after done!"));
      return;
    }
    t && this.write(t), this.ended = !0, this.tokenizer.end();
  }
  /**
   * Pauses parsing. The parser won't emit events until `resume` is called.
   */
  pause() {
    this.tokenizer.pause();
  }
  /**
   * Resumes parsing after `pause` was called.
   */
  resume() {
    for (this.tokenizer.resume(); this.tokenizer.running && this.writeIndex < this.buffers.length; )
      this.tokenizer.write(this.buffers[this.writeIndex++]);
    this.ended && this.tokenizer.end();
  }
  /**
   * Alias of `write`, for backwards compatibility.
   *
   * @param chunk Chunk to parse.
   * @deprecated
   */
  parseChunk(t) {
    this.write(t);
  }
  /**
   * Alias of `end`, for backwards compatibility.
   *
   * @param chunk Optional final chunk to parse.
   * @deprecated
   */
  done(t) {
    this.end(t);
  }
}
export {
  y as Parser
};
