import { determineBranch as m, BinTrieFlags as c } from "./index-decode.js";
import x from "./index-decode-data-xml.js";
import b from "./index-decode-data-html.js";
import { replaceCodePoint as I } from "./index-decode_codepoint.js";
var s;
(function(e) {
  e[e.Tab = 9] = "Tab", e[e.NewLine = 10] = "NewLine", e[e.FormFeed = 12] = "FormFeed", e[e.CarriageReturn = 13] = "CarriageReturn", e[e.Space = 32] = "Space", e[e.ExclamationMark = 33] = "ExclamationMark", e[e.Number = 35] = "Number", e[e.Amp = 38] = "Amp", e[e.SingleQuote = 39] = "SingleQuote", e[e.DoubleQuote = 34] = "DoubleQuote", e[e.Dash = 45] = "Dash", e[e.Slash = 47] = "Slash", e[e.Zero = 48] = "Zero", e[e.Nine = 57] = "Nine", e[e.Semi = 59] = "Semi", e[e.Lt = 60] = "Lt", e[e.Eq = 61] = "Eq", e[e.Gt = 62] = "Gt", e[e.Questionmark = 63] = "Questionmark", e[e.UpperA = 65] = "UpperA", e[e.LowerA = 97] = "LowerA", e[e.UpperF = 70] = "UpperF", e[e.LowerF = 102] = "LowerF", e[e.UpperZ = 90] = "UpperZ", e[e.LowerZ = 122] = "LowerZ", e[e.LowerX = 120] = "LowerX", e[e.OpeningSquareBracket = 91] = "OpeningSquareBracket";
})(s || (s = {}));
var i;
(function(e) {
  e[e.Text = 1] = "Text", e[e.BeforeTagName = 2] = "BeforeTagName", e[e.InTagName = 3] = "InTagName", e[e.InSelfClosingTag = 4] = "InSelfClosingTag", e[e.BeforeClosingTagName = 5] = "BeforeClosingTagName", e[e.InClosingTagName = 6] = "InClosingTagName", e[e.AfterClosingTagName = 7] = "AfterClosingTagName", e[e.BeforeAttributeName = 8] = "BeforeAttributeName", e[e.InAttributeName = 9] = "InAttributeName", e[e.AfterAttributeName = 10] = "AfterAttributeName", e[e.BeforeAttributeValue = 11] = "BeforeAttributeValue", e[e.InAttributeValueDq = 12] = "InAttributeValueDq", e[e.InAttributeValueSq = 13] = "InAttributeValueSq", e[e.InAttributeValueNq = 14] = "InAttributeValueNq", e[e.BeforeDeclaration = 15] = "BeforeDeclaration", e[e.InDeclaration = 16] = "InDeclaration", e[e.InProcessingInstruction = 17] = "InProcessingInstruction", e[e.BeforeComment = 18] = "BeforeComment", e[e.CDATASequence = 19] = "CDATASequence", e[e.InSpecialComment = 20] = "InSpecialComment", e[e.InCommentLike = 21] = "InCommentLike", e[e.BeforeSpecialS = 22] = "BeforeSpecialS", e[e.SpecialStartSequence = 23] = "SpecialStartSequence", e[e.InSpecialTag = 24] = "InSpecialTag", e[e.BeforeEntity = 25] = "BeforeEntity", e[e.BeforeNumericEntity = 26] = "BeforeNumericEntity", e[e.InNamedEntity = 27] = "InNamedEntity", e[e.InNumericEntity = 28] = "InNumericEntity", e[e.InHexEntity = 29] = "InHexEntity";
})(i || (i = {}));
function h(e) {
  return e === s.Space || e === s.NewLine || e === s.Tab || e === s.FormFeed || e === s.CarriageReturn;
}
function u(e) {
  return e === s.Slash || e === s.Gt || h(e);
}
function f(e) {
  return e >= s.Zero && e <= s.Nine;
}
function d(e) {
  return e >= s.LowerA && e <= s.LowerZ || e >= s.UpperA && e <= s.UpperZ;
}
function S(e) {
  return e >= s.UpperA && e <= s.UpperF || e >= s.LowerA && e <= s.LowerF;
}
var o;
(function(e) {
  e[e.NoValue = 0] = "NoValue", e[e.Unquoted = 1] = "Unquoted", e[e.Single = 2] = "Single", e[e.Double = 3] = "Double";
})(o || (o = {}));
const a = {
  Cdata: new Uint8Array([67, 68, 65, 84, 65, 91]),
  CdataEnd: new Uint8Array([93, 93, 62]),
  CommentEnd: new Uint8Array([45, 45, 62]),
  ScriptEnd: new Uint8Array([60, 47, 115, 99, 114, 105, 112, 116]),
  StyleEnd: new Uint8Array([60, 47, 115, 116, 121, 108, 101]),
  TitleEnd: new Uint8Array([60, 47, 116, 105, 116, 108, 101])
  // `</title`
};
class E {
  constructor({ xmlMode: t = !1, decodeEntities: n = !0 }, r) {
    this.cbs = r, this.state = i.Text, this.buffer = "", this.sectionStart = 0, this.index = 0, this.baseState = i.Text, this.isSpecial = !1, this.running = !0, this.offset = 0, this.currentSequence = void 0, this.sequenceIndex = 0, this.trieIndex = 0, this.trieCurrent = 0, this.entityResult = 0, this.entityExcess = 0, this.xmlMode = t, this.decodeEntities = n, this.entityTrie = t ? x : b;
  }
  reset() {
    this.state = i.Text, this.buffer = "", this.sectionStart = 0, this.index = 0, this.baseState = i.Text, this.currentSequence = void 0, this.running = !0, this.offset = 0;
  }
  write(t) {
    this.offset += this.buffer.length, this.buffer = t, this.parse();
  }
  end() {
    this.running && this.finish();
  }
  pause() {
    this.running = !1;
  }
  resume() {
    this.running = !0, this.index < this.buffer.length + this.offset && this.parse();
  }
  /**
   * The current index within all of the written data.
   */
  getIndex() {
    return this.index;
  }
  /**
   * The start of the current section.
   */
  getSectionStart() {
    return this.sectionStart;
  }
  stateText(t) {
    t === s.Lt || !this.decodeEntities && this.fastForwardTo(s.Lt) ? (this.index > this.sectionStart && this.cbs.ontext(this.sectionStart, this.index), this.state = i.BeforeTagName, this.sectionStart = this.index) : this.decodeEntities && t === s.Amp && (this.state = i.BeforeEntity);
  }
  stateSpecialStartSequence(t) {
    const n = this.sequenceIndex === this.currentSequence.length;
    if (!(n ? (
      // If we are at the end of the sequence, make sure the tag name has ended
      u(t)
    ) : (
      // Otherwise, do a case-insensitive comparison
      (t | 32) === this.currentSequence[this.sequenceIndex]
    )))
      this.isSpecial = !1;
    else if (!n) {
      this.sequenceIndex++;
      return;
    }
    this.sequenceIndex = 0, this.state = i.InTagName, this.stateInTagName(t);
  }
  /** Look for an end tag. For <title> tags, also decode entities. */
  stateInSpecialTag(t) {
    if (this.sequenceIndex === this.currentSequence.length) {
      if (t === s.Gt || h(t)) {
        const n = this.index - this.currentSequence.length;
        if (this.sectionStart < n) {
          const r = this.index;
          this.index = n, this.cbs.ontext(this.sectionStart, n), this.index = r;
        }
        this.isSpecial = !1, this.sectionStart = n + 2, this.stateInClosingTagName(t);
        return;
      }
      this.sequenceIndex = 0;
    }
    (t | 32) === this.currentSequence[this.sequenceIndex] ? this.sequenceIndex += 1 : this.sequenceIndex === 0 ? this.currentSequence === a.TitleEnd ? this.decodeEntities && t === s.Amp && (this.state = i.BeforeEntity) : this.fastForwardTo(s.Lt) && (this.sequenceIndex = 1) : this.sequenceIndex = +(t === s.Lt);
  }
  stateCDATASequence(t) {
    t === a.Cdata[this.sequenceIndex] ? ++this.sequenceIndex === a.Cdata.length && (this.state = i.InCommentLike, this.currentSequence = a.CdataEnd, this.sequenceIndex = 0, this.sectionStart = this.index + 1) : (this.sequenceIndex = 0, this.state = i.InDeclaration, this.stateInDeclaration(t));
  }
  /**
   * When we wait for one specific character, we can speed things up
   * by skipping through the buffer until we find it.
   *
   * @returns Whether the character was found.
   */
  fastForwardTo(t) {
    for (; ++this.index < this.buffer.length + this.offset; )
      if (this.buffer.charCodeAt(this.index - this.offset) === t)
        return !0;
    return this.index = this.buffer.length + this.offset - 1, !1;
  }
  /**
   * Comments and CDATA end with `-->` and `]]>`.
   *
   * Their common qualities are:
   * - Their end sequences have a distinct character they start with.
   * - That character is then repeated, so we have to check multiple repeats.
   * - All characters but the start character of the sequence can be skipped.
   */
  stateInCommentLike(t) {
    t === this.currentSequence[this.sequenceIndex] ? ++this.sequenceIndex === this.currentSequence.length && (this.currentSequence === a.CdataEnd ? this.cbs.oncdata(this.sectionStart, this.index, 2) : this.cbs.oncomment(this.sectionStart, this.index, 2), this.sequenceIndex = 0, this.sectionStart = this.index + 1, this.state = i.Text) : this.sequenceIndex === 0 ? this.fastForwardTo(this.currentSequence[0]) && (this.sequenceIndex = 1) : t !== this.currentSequence[this.sequenceIndex - 1] && (this.sequenceIndex = 0);
  }
  /**
   * HTML only allows ASCII alpha characters (a-z and A-Z) at the beginning of a tag name.
   *
   * XML allows a lot more characters here (@see https://www.w3.org/TR/REC-xml/#NT-NameStartChar).
   * We allow anything that wouldn't end the tag.
   */
  isTagStartChar(t) {
    return this.xmlMode ? !u(t) : d(t);
  }
  startSpecial(t, n) {
    this.isSpecial = !0, this.currentSequence = t, this.sequenceIndex = n, this.state = i.SpecialStartSequence;
  }
  stateBeforeTagName(t) {
    if (t === s.ExclamationMark)
      this.state = i.BeforeDeclaration, this.sectionStart = this.index + 1;
    else if (t === s.Questionmark)
      this.state = i.InProcessingInstruction, this.sectionStart = this.index + 1;
    else if (this.isTagStartChar(t)) {
      const n = t | 32;
      this.sectionStart = this.index, !this.xmlMode && n === a.TitleEnd[2] ? this.startSpecial(a.TitleEnd, 3) : this.state = !this.xmlMode && n === a.ScriptEnd[2] ? i.BeforeSpecialS : i.InTagName;
    } else t === s.Slash ? this.state = i.BeforeClosingTagName : (this.state = i.Text, this.stateText(t));
  }
  stateInTagName(t) {
    u(t) && (this.cbs.onopentagname(this.sectionStart, this.index), this.sectionStart = -1, this.state = i.BeforeAttributeName, this.stateBeforeAttributeName(t));
  }
  stateBeforeClosingTagName(t) {
    h(t) || (t === s.Gt ? this.state = i.Text : (this.state = this.isTagStartChar(t) ? i.InClosingTagName : i.InSpecialComment, this.sectionStart = this.index));
  }
  stateInClosingTagName(t) {
    (t === s.Gt || h(t)) && (this.cbs.onclosetag(this.sectionStart, this.index), this.sectionStart = -1, this.state = i.AfterClosingTagName, this.stateAfterClosingTagName(t));
  }
  stateAfterClosingTagName(t) {
    (t === s.Gt || this.fastForwardTo(s.Gt)) && (this.state = i.Text, this.baseState = i.Text, this.sectionStart = this.index + 1);
  }
  stateBeforeAttributeName(t) {
    t === s.Gt ? (this.cbs.onopentagend(this.index), this.isSpecial ? (this.state = i.InSpecialTag, this.sequenceIndex = 0) : this.state = i.Text, this.baseState = this.state, this.sectionStart = this.index + 1) : t === s.Slash ? this.state = i.InSelfClosingTag : h(t) || (this.state = i.InAttributeName, this.sectionStart = this.index);
  }
  stateInSelfClosingTag(t) {
    t === s.Gt ? (this.cbs.onselfclosingtag(this.index), this.state = i.Text, this.baseState = i.Text, this.sectionStart = this.index + 1, this.isSpecial = !1) : h(t) || (this.state = i.BeforeAttributeName, this.stateBeforeAttributeName(t));
  }
  stateInAttributeName(t) {
    (t === s.Eq || u(t)) && (this.cbs.onattribname(this.sectionStart, this.index), this.sectionStart = -1, this.state = i.AfterAttributeName, this.stateAfterAttributeName(t));
  }
  stateAfterAttributeName(t) {
    t === s.Eq ? this.state = i.BeforeAttributeValue : t === s.Slash || t === s.Gt ? (this.cbs.onattribend(o.NoValue, this.index), this.state = i.BeforeAttributeName, this.stateBeforeAttributeName(t)) : h(t) || (this.cbs.onattribend(o.NoValue, this.index), this.state = i.InAttributeName, this.sectionStart = this.index);
  }
  stateBeforeAttributeValue(t) {
    t === s.DoubleQuote ? (this.state = i.InAttributeValueDq, this.sectionStart = this.index + 1) : t === s.SingleQuote ? (this.state = i.InAttributeValueSq, this.sectionStart = this.index + 1) : h(t) || (this.sectionStart = this.index, this.state = i.InAttributeValueNq, this.stateInAttributeValueNoQuotes(t));
  }
  handleInAttributeValue(t, n) {
    t === n || !this.decodeEntities && this.fastForwardTo(n) ? (this.cbs.onattribdata(this.sectionStart, this.index), this.sectionStart = -1, this.cbs.onattribend(n === s.DoubleQuote ? o.Double : o.Single, this.index), this.state = i.BeforeAttributeName) : this.decodeEntities && t === s.Amp && (this.baseState = this.state, this.state = i.BeforeEntity);
  }
  stateInAttributeValueDoubleQuotes(t) {
    this.handleInAttributeValue(t, s.DoubleQuote);
  }
  stateInAttributeValueSingleQuotes(t) {
    this.handleInAttributeValue(t, s.SingleQuote);
  }
  stateInAttributeValueNoQuotes(t) {
    h(t) || t === s.Gt ? (this.cbs.onattribdata(this.sectionStart, this.index), this.sectionStart = -1, this.cbs.onattribend(o.Unquoted, this.index), this.state = i.BeforeAttributeName, this.stateBeforeAttributeName(t)) : this.decodeEntities && t === s.Amp && (this.baseState = this.state, this.state = i.BeforeEntity);
  }
  stateBeforeDeclaration(t) {
    t === s.OpeningSquareBracket ? (this.state = i.CDATASequence, this.sequenceIndex = 0) : this.state = t === s.Dash ? i.BeforeComment : i.InDeclaration;
  }
  stateInDeclaration(t) {
    (t === s.Gt || this.fastForwardTo(s.Gt)) && (this.cbs.ondeclaration(this.sectionStart, this.index), this.state = i.Text, this.sectionStart = this.index + 1);
  }
  stateInProcessingInstruction(t) {
    (t === s.Gt || this.fastForwardTo(s.Gt)) && (this.cbs.onprocessinginstruction(this.sectionStart, this.index), this.state = i.Text, this.sectionStart = this.index + 1);
  }
  stateBeforeComment(t) {
    t === s.Dash ? (this.state = i.InCommentLike, this.currentSequence = a.CommentEnd, this.sequenceIndex = 2, this.sectionStart = this.index + 1) : this.state = i.InDeclaration;
  }
  stateInSpecialComment(t) {
    (t === s.Gt || this.fastForwardTo(s.Gt)) && (this.cbs.oncomment(this.sectionStart, this.index, 0), this.state = i.Text, this.sectionStart = this.index + 1);
  }
  stateBeforeSpecialS(t) {
    const n = t | 32;
    n === a.ScriptEnd[3] ? this.startSpecial(a.ScriptEnd, 4) : n === a.StyleEnd[3] ? this.startSpecial(a.StyleEnd, 4) : (this.state = i.InTagName, this.stateInTagName(t));
  }
  stateBeforeEntity(t) {
    this.entityExcess = 1, this.entityResult = 0, t === s.Number ? this.state = i.BeforeNumericEntity : t === s.Amp || (this.trieIndex = 0, this.trieCurrent = this.entityTrie[0], this.state = i.InNamedEntity, this.stateInNamedEntity(t));
  }
  stateInNamedEntity(t) {
    if (this.entityExcess += 1, this.trieIndex = m(this.entityTrie, this.trieCurrent, this.trieIndex + 1, t), this.trieIndex < 0) {
      this.emitNamedEntity(), this.index--;
      return;
    }
    this.trieCurrent = this.entityTrie[this.trieIndex];
    const n = this.trieCurrent & c.VALUE_LENGTH;
    if (n) {
      const r = (n >> 14) - 1;
      if (!this.allowLegacyEntity() && t !== s.Semi)
        this.trieIndex += r;
      else {
        const l = this.index - this.entityExcess + 1;
        l > this.sectionStart && this.emitPartial(this.sectionStart, l), this.entityResult = this.trieIndex, this.trieIndex += r, this.entityExcess = 0, this.sectionStart = this.index + 1, r === 0 && this.emitNamedEntity();
      }
    }
  }
  emitNamedEntity() {
    if (this.state = this.baseState, this.entityResult === 0)
      return;
    switch ((this.entityTrie[this.entityResult] & c.VALUE_LENGTH) >> 14) {
      case 1: {
        this.emitCodePoint(this.entityTrie[this.entityResult] & ~c.VALUE_LENGTH);
        break;
      }
      case 2: {
        this.emitCodePoint(this.entityTrie[this.entityResult + 1]);
        break;
      }
      case 3:
        this.emitCodePoint(this.entityTrie[this.entityResult + 1]), this.emitCodePoint(this.entityTrie[this.entityResult + 2]);
    }
  }
  stateBeforeNumericEntity(t) {
    (t | 32) === s.LowerX ? (this.entityExcess++, this.state = i.InHexEntity) : (this.state = i.InNumericEntity, this.stateInNumericEntity(t));
  }
  emitNumericEntity(t) {
    const n = this.index - this.entityExcess - 1;
    n + 2 + +(this.state === i.InHexEntity) !== this.index && (n > this.sectionStart && this.emitPartial(this.sectionStart, n), this.sectionStart = this.index + Number(t), this.emitCodePoint(I(this.entityResult))), this.state = this.baseState;
  }
  stateInNumericEntity(t) {
    t === s.Semi ? this.emitNumericEntity(!0) : f(t) ? (this.entityResult = this.entityResult * 10 + (t - s.Zero), this.entityExcess++) : (this.allowLegacyEntity() ? this.emitNumericEntity(!1) : this.state = this.baseState, this.index--);
  }
  stateInHexEntity(t) {
    t === s.Semi ? this.emitNumericEntity(!0) : f(t) ? (this.entityResult = this.entityResult * 16 + (t - s.Zero), this.entityExcess++) : S(t) ? (this.entityResult = this.entityResult * 16 + ((t | 32) - s.LowerA + 10), this.entityExcess++) : (this.allowLegacyEntity() ? this.emitNumericEntity(!1) : this.state = this.baseState, this.index--);
  }
  allowLegacyEntity() {
    return !this.xmlMode && (this.baseState === i.Text || this.baseState === i.InSpecialTag);
  }
  /**
   * Remove data that has already been consumed from the buffer.
   */
  cleanup() {
    this.running && this.sectionStart !== this.index && (this.state === i.Text || this.state === i.InSpecialTag && this.sequenceIndex === 0 ? (this.cbs.ontext(this.sectionStart, this.index), this.sectionStart = this.index) : (this.state === i.InAttributeValueDq || this.state === i.InAttributeValueSq || this.state === i.InAttributeValueNq) && (this.cbs.onattribdata(this.sectionStart, this.index), this.sectionStart = this.index));
  }
  shouldContinue() {
    return this.index < this.buffer.length + this.offset && this.running;
  }
  /**
   * Iterates through the buffer, calling the function corresponding to the current state.
   *
   * States that are more likely to be hit are higher up, as a performance improvement.
   */
  parse() {
    for (; this.shouldContinue(); ) {
      const t = this.buffer.charCodeAt(this.index - this.offset);
      switch (this.state) {
        case i.Text: {
          this.stateText(t);
          break;
        }
        case i.SpecialStartSequence: {
          this.stateSpecialStartSequence(t);
          break;
        }
        case i.InSpecialTag: {
          this.stateInSpecialTag(t);
          break;
        }
        case i.CDATASequence: {
          this.stateCDATASequence(t);
          break;
        }
        case i.InAttributeValueDq: {
          this.stateInAttributeValueDoubleQuotes(t);
          break;
        }
        case i.InAttributeName: {
          this.stateInAttributeName(t);
          break;
        }
        case i.InCommentLike: {
          this.stateInCommentLike(t);
          break;
        }
        case i.InSpecialComment: {
          this.stateInSpecialComment(t);
          break;
        }
        case i.BeforeAttributeName: {
          this.stateBeforeAttributeName(t);
          break;
        }
        case i.InTagName: {
          this.stateInTagName(t);
          break;
        }
        case i.InClosingTagName: {
          this.stateInClosingTagName(t);
          break;
        }
        case i.BeforeTagName: {
          this.stateBeforeTagName(t);
          break;
        }
        case i.AfterAttributeName: {
          this.stateAfterAttributeName(t);
          break;
        }
        case i.InAttributeValueSq: {
          this.stateInAttributeValueSingleQuotes(t);
          break;
        }
        case i.BeforeAttributeValue: {
          this.stateBeforeAttributeValue(t);
          break;
        }
        case i.BeforeClosingTagName: {
          this.stateBeforeClosingTagName(t);
          break;
        }
        case i.AfterClosingTagName: {
          this.stateAfterClosingTagName(t);
          break;
        }
        case i.BeforeSpecialS: {
          this.stateBeforeSpecialS(t);
          break;
        }
        case i.InAttributeValueNq: {
          this.stateInAttributeValueNoQuotes(t);
          break;
        }
        case i.InSelfClosingTag: {
          this.stateInSelfClosingTag(t);
          break;
        }
        case i.InDeclaration: {
          this.stateInDeclaration(t);
          break;
        }
        case i.BeforeDeclaration: {
          this.stateBeforeDeclaration(t);
          break;
        }
        case i.BeforeComment: {
          this.stateBeforeComment(t);
          break;
        }
        case i.InProcessingInstruction: {
          this.stateInProcessingInstruction(t);
          break;
        }
        case i.InNamedEntity: {
          this.stateInNamedEntity(t);
          break;
        }
        case i.BeforeEntity: {
          this.stateBeforeEntity(t);
          break;
        }
        case i.InHexEntity: {
          this.stateInHexEntity(t);
          break;
        }
        case i.InNumericEntity: {
          this.stateInNumericEntity(t);
          break;
        }
        default:
          this.stateBeforeNumericEntity(t);
      }
      this.index++;
    }
    this.cleanup();
  }
  finish() {
    this.state === i.InNamedEntity && this.emitNamedEntity(), this.sectionStart < this.index && this.handleTrailingData(), this.cbs.onend();
  }
  /** Handle any trailing data. */
  handleTrailingData() {
    const t = this.buffer.length + this.offset;
    this.state === i.InCommentLike ? this.currentSequence === a.CdataEnd ? this.cbs.oncdata(this.sectionStart, t, 0) : this.cbs.oncomment(this.sectionStart, t, 0) : this.state === i.InNumericEntity && this.allowLegacyEntity() ? this.emitNumericEntity(!1) : this.state === i.InHexEntity && this.allowLegacyEntity() ? this.emitNumericEntity(!1) : this.state === i.InTagName || this.state === i.BeforeAttributeName || this.state === i.BeforeAttributeValue || this.state === i.AfterAttributeName || this.state === i.InAttributeName || this.state === i.InAttributeValueSq || this.state === i.InAttributeValueDq || this.state === i.InAttributeValueNq || this.state === i.InClosingTagName || this.cbs.ontext(this.sectionStart, t);
  }
  emitPartial(t, n) {
    this.baseState !== i.Text && this.baseState !== i.InSpecialTag ? this.cbs.onattribdata(t, n) : this.cbs.ontext(t, n);
  }
  emitCodePoint(t) {
    this.baseState !== i.Text && this.baseState !== i.InSpecialTag ? this.cbs.onattribentity(t) : this.cbs.ontextentity(t);
  }
}
export {
  o as QuoteType,
  E as default
};
