/// This library has a parser for HTML5 documents, that lets you parse HTML
/// easily from a script or server side application:
///
///     import 'package:html/parser.dart' show parse;
///     import 'package:html/dom.dart';
///     main() {
///       var document = parse(
///           '<body>Hello world! <a href="www.html5rocks.com">HTML5 rocks!');
///       print(document.outerHtml);
///     }
///
/// The resulting document you get back has a DOM-like API for easy tree
/// traversal and manipulation.
library;

import 'dart:collection';
import 'dart:math';

import 'package:source_span/source_span.dart';

import 'dom.dart';
import 'src/constants.dart';
import 'src/encoding_parser.dart';
import 'src/token.dart';
import 'src/tokenizer.dart';
import 'src/treebuilder.dart';
import 'src/utils.dart';

/// Parse an html5 document into a tree.
///
/// The [input] can be a `String`, a `List<int>` of bytes, or an
/// [HtmlTokenizer].
///
/// If [input] is not a [HtmlTokenizer], you can optionally specify the file's
/// [encoding], which must be a string. If specified that encoding will be
/// used regardless of any BOM or later declaration (such as in a meta element).
///
/// Set [generateSpans] if you want to generate [SourceSpan]s, otherwise the
/// [Node.sourceSpan] property will be `null`. When using [generateSpans] you
/// can additionally pass [sourceUrl] to indicate where the [input] was
/// extracted from.
Document parse(dynamic input,
    {String? encoding, bool generateSpans = false, String? sourceUrl}) {
  final p = HtmlParser(input,
      encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl);
  return p.parse();
}

/// Parse an html5 document fragment into a tree.
///
/// The [input] can be a `String`, a `List<int>` of bytes, or an
/// [HtmlTokenizer].
/// The [container] element can optionally be specified, otherwise it defaults
/// to "div".
///
/// If [input] is not a [HtmlTokenizer], you can optionally specify the file's
/// [encoding], which must be a string. If specified, that encoding will be used,
/// regardless of any BOM or later declaration (such as in a meta element).
///
/// Set [generateSpans] if you want to generate [SourceSpan]s, otherwise the
/// [Node.sourceSpan] property will be `null`. When using [generateSpans] you can
/// additionally pass [sourceUrl] to indicate where the [input] was extracted
/// from.
DocumentFragment parseFragment(dynamic input,
    {String container = 'div',
    String? encoding,
    bool generateSpans = false,
    String? sourceUrl}) {
  final p = HtmlParser(input,
      encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl);
  return p.parseFragment(container);
}

/// Parser for HTML, which generates a tree structure from a stream of
/// (possibly malformed) characters.
class HtmlParser {
  /// Raise an exception on the first error encountered.
  final bool strict;

  /// True to generate [SourceSpan]s for the [Node.sourceSpan] property.
  final bool generateSpans;

  final HtmlTokenizer tokenizer;

  final TreeBuilder tree;

  final List<ParseError> errors = <ParseError>[];

  bool firstStartTag = false;

  // TODO(jmesserly): use enum?
  /// "quirks" / "limited quirks" / "no quirks"
  String compatMode = 'no quirks';

  /// innerHTML container when parsing document fragment.
  String? innerHTML;

  late Phase phase = _initialPhase;

  Phase? originalPhase;

  bool framesetOK = true;

  // These fields hold the different phase singletons. At any given time one
  // of them will be active.
  late final _initialPhase = InitialPhase(this);
  late final _beforeHtmlPhase = BeforeHtmlPhase(this);
  late final _beforeHeadPhase = BeforeHeadPhase(this);
  late final _inHeadPhase = InHeadPhase(this);
  // TODO: html5lib did not implement the no script parsing mode
  // More information here:
  // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#scripting-flag
  // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#parsing-main-inheadnoscript
  // late final _inHeadNoscript = InHeadNoScriptPhase(this);
  late final _afterHeadPhase = AfterHeadPhase(this);
  late final _inBodyPhase = InBodyPhase(this);
  late final _textPhase = TextPhase(this);
  late final _inTablePhase = InTablePhase(this);
  late final _inTableTextPhase = InTableTextPhase(this);
  late final _inCaptionPhase = InCaptionPhase(this);
  late final _inColumnGroupPhase = InColumnGroupPhase(this);
  late final _inTableBodyPhase = InTableBodyPhase(this);
  late final _inRowPhase = InRowPhase(this);
  late final _inCellPhase = InCellPhase(this);
  late final _inSelectPhase = InSelectPhase(this);
  late final _inSelectInTablePhase = InSelectInTablePhase(this);
  late final _inForeignContentPhase = InForeignContentPhase(this);
  late final _afterBodyPhase = AfterBodyPhase(this);
  late final _inFramesetPhase = InFramesetPhase(this);
  late final _afterFramesetPhase = AfterFramesetPhase(this);
  late final _afterAfterBodyPhase = AfterAfterBodyPhase(this);
  late final _afterAfterFramesetPhase = AfterAfterFramesetPhase(this);

  /// Create and configure an HtmlParser.
  ///
  /// The [input] can be a `String`, a `List<int>` of bytes, or an
  /// [HtmlTokenizer].
  ///
  /// The [strict], [tree] builder, and [generateSpans] arguments configure
  /// behavior for any type of input.
  ///
  /// If [input] is not a [HtmlTokenizer], you can specify a few more arguments.
  ///
  /// The [encoding] must be a string that indicates the encoding. If specified,
  /// that encoding will be used, regardless of any BOM or later declaration
  /// (such as in a meta element).
  ///
  /// Set [parseMeta] to false if you want to disable parsing the meta element.
  ///
  /// Set [lowercaseElementName] or [lowercaseAttrName] to false to disable the
  /// automatic conversion of element and attribute names to lower case. Note
  /// that standard way to parse HTML is to lowercase, which is what the browser
  /// DOM will do if you request `Element.outerHTML`, for example.
  HtmlParser(
    dynamic input, {
    TreeBuilder? tree,
    this.strict = false,
    this.generateSpans = false,
    String? encoding,
    bool parseMeta = true,
    bool lowercaseElementName = true,
    bool lowercaseAttrName = true,
    String? sourceUrl,
  })  : tree = tree ?? TreeBuilder(true),
        tokenizer = input is HtmlTokenizer
            ? input
            : HtmlTokenizer(input,
                encoding: encoding,
                parseMeta: parseMeta,
                lowercaseElementName: lowercaseElementName,
                lowercaseAttrName: lowercaseAttrName,
                generateSpans: generateSpans,
                sourceUrl: sourceUrl) {
    tokenizer.parser = this;
  }

  bool get innerHTMLMode => innerHTML != null;

  /// Parse an html5 document into a tree.
  ///
  /// After parsing, [errors] will be populated with parse errors, if any.
  Document parse() {
    innerHTML = null;
    _parse();
    return tree.getDocument();
  }

  /// Parse an html5 document fragment into a tree.
  ///
  /// Pass a [container] to change the type of the containing element.
  /// After parsing, [errors] will be populated with parse errors, if any.
  DocumentFragment parseFragment([String container = 'div']) {
    ArgumentError.checkNotNull(container, 'container');
    innerHTML = container.toLowerCase();
    _parse();
    return tree.getFragment();
  }

  void _parse() {
    reset();

    while (true) {
      try {
        mainLoop();
        break;
      } on ReparseException catch (_) {
        // Note: this happens if we start parsing but the character encoding
        // changes. So we should only need to restart very early in the parse.
        reset();
      }
    }
  }

  void reset() {
    tokenizer.reset();

    tree.reset();
    firstStartTag = false;
    errors.clear();
    // "quirks" / "limited quirks" / "no quirks"
    compatMode = 'no quirks';

    if (innerHTMLMode) {
      if (cdataElements.contains(innerHTML)) {
        tokenizer.state = tokenizer.rcdataState;
      } else if (rcdataElements.contains(innerHTML)) {
        tokenizer.state = tokenizer.rawtextState;
      } else if (innerHTML == 'plaintext') {
        tokenizer.state = tokenizer.plaintextState;
      } else {
        // state already is data state
        // tokenizer.state = tokenizer.dataState;
      }
      phase = _beforeHtmlPhase;
      _beforeHtmlPhase.insertHtmlElement();
      resetInsertionMode();
    } else {
      phase = _initialPhase;
    }

    framesetOK = true;
  }

  bool isHTMLIntegrationPoint(Element element) {
    if (element.localName == 'annotation-xml' &&
        element.namespaceUri == Namespaces.mathml) {
      final enc = element.attributes['encoding']?.toAsciiLowerCase();
      return enc == 'text/html' || enc == 'application/xhtml+xml';
    } else {
      return htmlIntegrationPointElements
          .contains((element.namespaceUri, element.localName));
    }
  }

  bool isMathMLTextIntegrationPoint(Element element) {
    return mathmlTextIntegrationPointElements
        .contains((element.namespaceUri, element.localName));
  }

  bool inForeignContent(Token token, int type) {
    if (tree.openElements.isEmpty) return false;

    final node = tree.openElements.last;
    if (node.namespaceUri == tree.defaultNamespace) return false;

    if (isMathMLTextIntegrationPoint(node)) {
      if (type == TokenKind.startTag &&
          (token as StartTagToken).name != 'mglyph' &&
          token.name != 'malignmark') {
        return false;
      }
      if (type == TokenKind.characters || type == TokenKind.spaceCharacters) {
        return false;
      }
    }

    if (node.localName == 'annotation-xml' &&
        type == TokenKind.startTag &&
        (token as StartTagToken).name == 'svg') {
      return false;
    }

    if (isHTMLIntegrationPoint(node)) {
      if (type == TokenKind.startTag ||
          type == TokenKind.characters ||
          type == TokenKind.spaceCharacters) {
        return false;
      }
    }

    return true;
  }

  void mainLoop() {
    while (tokenizer.moveNext()) {
      final token = tokenizer.current;
      Token? newToken = token;
      int type;
      while (newToken != null) {
        type = newToken.kind;

        // Note: avoid "is" test here, see http://dartbug.com/4795
        if (type == TokenKind.parseError) {
          final error = newToken as ParseErrorToken;
          parseError(error.span, error.data, error.messageParams);
          newToken = null;
        } else {
          var localPhase = phase;
          if (inForeignContent(token, type)) {
            localPhase = _inForeignContentPhase;
          }

          switch (type) {
            case TokenKind.characters:
              newToken =
                  localPhase.processCharacters(newToken as CharactersToken);
              break;
            case TokenKind.spaceCharacters:
              newToken = localPhase
                  .processSpaceCharacters(newToken as SpaceCharactersToken);
              break;
            case TokenKind.startTag:
              newToken = localPhase.processStartTag(newToken as StartTagToken);
              break;
            case TokenKind.endTag:
              newToken = localPhase.processEndTag(newToken as EndTagToken);
              break;
            case TokenKind.comment:
              newToken = localPhase.processComment(newToken as CommentToken);
              break;
            case TokenKind.doctype:
              newToken = localPhase.processDoctype(newToken as DoctypeToken);
              break;
          }
        }
      }

      if (token is StartTagToken) {
        if (token.selfClosing && !token.selfClosingAcknowledged) {
          parseError(token.span, 'non-void-element-with-trailing-solidus',
              {'name': token.name});
        }
      }
    }

    // When the loop finishes it's EOF
    var reprocess = true;
    final reprocessPhases = <Phase>[];
    while (reprocess) {
      reprocessPhases.add(phase);
      reprocess = phase.processEOF();
      if (reprocess) {
        assert(!reprocessPhases.contains(phase));
      }
    }
  }

  /// The last span available. Used for EOF errors if we don't have something
  /// better.
  SourceSpan? get _lastSpan => tokenizer.stream.fileInfo
      ?.location(tokenizer.stream.position)
      .pointSpan();

  void parseError(SourceSpan? span, String errorcode,
      [Map<String, Object?>? datavars = const {}]) {
    if (!generateSpans && span == null) {
      span = _lastSpan;
    }

    final err = ParseError(errorcode, span, datavars);
    errors.add(err);
    if (strict) throw err;
  }

  void adjustMathMLAttributes(StartTagToken token) {
    final orig = token.data.remove('definitionurl');
    if (orig != null) {
      token.data['definitionURL'] = orig;
    }
  }

  void adjustSVGAttributes(StartTagToken token) {
    final replacements = const {
      'attributename': 'attributeName',
      'attributetype': 'attributeType',
      'basefrequency': 'baseFrequency',
      'baseprofile': 'baseProfile',
      'calcmode': 'calcMode',
      'clippathunits': 'clipPathUnits',
      'contentscripttype': 'contentScriptType',
      'contentstyletype': 'contentStyleType',
      'diffuseconstant': 'diffuseConstant',
      'edgemode': 'edgeMode',
      'externalresourcesrequired': 'externalResourcesRequired',
      'filterres': 'filterRes',
      'filterunits': 'filterUnits',
      'glyphref': 'glyphRef',
      'gradienttransform': 'gradientTransform',
      'gradientunits': 'gradientUnits',
      'kernelmatrix': 'kernelMatrix',
      'kernelunitlength': 'kernelUnitLength',
      'keypoints': 'keyPoints',
      'keysplines': 'keySplines',
      'keytimes': 'keyTimes',
      'lengthadjust': 'lengthAdjust',
      'limitingconeangle': 'limitingConeAngle',
      'markerheight': 'markerHeight',
      'markerunits': 'markerUnits',
      'markerwidth': 'markerWidth',
      'maskcontentunits': 'maskContentUnits',
      'maskunits': 'maskUnits',
      'numoctaves': 'numOctaves',
      'pathlength': 'pathLength',
      'patterncontentunits': 'patternContentUnits',
      'patterntransform': 'patternTransform',
      'patternunits': 'patternUnits',
      'pointsatx': 'pointsAtX',
      'pointsaty': 'pointsAtY',
      'pointsatz': 'pointsAtZ',
      'preservealpha': 'preserveAlpha',
      'preserveaspectratio': 'preserveAspectRatio',
      'primitiveunits': 'primitiveUnits',
      'refx': 'refX',
      'refy': 'refY',
      'repeatcount': 'repeatCount',
      'repeatdur': 'repeatDur',
      'requiredextensions': 'requiredExtensions',
      'requiredfeatures': 'requiredFeatures',
      'specularconstant': 'specularConstant',
      'specularexponent': 'specularExponent',
      'spreadmethod': 'spreadMethod',
      'startoffset': 'startOffset',
      'stddeviation': 'stdDeviation',
      'stitchtiles': 'stitchTiles',
      'surfacescale': 'surfaceScale',
      'systemlanguage': 'systemLanguage',
      'tablevalues': 'tableValues',
      'targetx': 'targetX',
      'targety': 'targetY',
      'textlength': 'textLength',
      'viewbox': 'viewBox',
      'viewtarget': 'viewTarget',
      'xchannelselector': 'xChannelSelector',
      'ychannelselector': 'yChannelSelector',
      'zoomandpan': 'zoomAndPan'
    };
    for (var originalName in token.data.keys.toList(growable: false)) {
      final svgName = replacements[originalName as String];
      if (svgName != null) {
        token.data[svgName] = token.data.remove(originalName)!;
      }
    }
  }

  void adjustForeignAttributes(StartTagToken token) {
    // TODO(jmesserly): I don't like mixing non-string objects with strings in
    // the Node.attributes Map. Is there another solution?
    final replacements = const {
      'xlink:actuate': AttributeName('xlink', 'actuate', Namespaces.xlink),
      'xlink:arcrole': AttributeName('xlink', 'arcrole', Namespaces.xlink),
      'xlink:href': AttributeName('xlink', 'href', Namespaces.xlink),
      'xlink:role': AttributeName('xlink', 'role', Namespaces.xlink),
      'xlink:show': AttributeName('xlink', 'show', Namespaces.xlink),
      'xlink:title': AttributeName('xlink', 'title', Namespaces.xlink),
      'xlink:type': AttributeName('xlink', 'type', Namespaces.xlink),
      'xml:base': AttributeName('xml', 'base', Namespaces.xml),
      'xml:lang': AttributeName('xml', 'lang', Namespaces.xml),
      'xml:space': AttributeName('xml', 'space', Namespaces.xml),
      'xmlns': AttributeName(null, 'xmlns', Namespaces.xmlns),
      'xmlns:xlink': AttributeName('xmlns', 'xlink', Namespaces.xmlns)
    };

    for (var originalName in token.data.keys.toList(growable: false)) {
      final foreignName = replacements[originalName as String];
      if (foreignName != null) {
        token.data[foreignName] = token.data.remove(originalName)!;
      }
    }
  }

  void resetInsertionMode() {
    // The name of this method is mostly historical. (It's also used in the
    // specification.)
    for (var node in tree.openElements.reversed) {
      var nodeName = node.localName;
      final last = node == tree.openElements[0];
      if (last) {
        assert(innerHTMLMode);
        nodeName = innerHTML;
      }
      // Check for conditions that should only happen in the innerHTML
      // case
      switch (nodeName) {
        case 'select':
        case 'colgroup':
        case 'head':
        case 'html':
          assert(innerHTMLMode);
          break;
      }
      if (!last && node.namespaceUri != tree.defaultNamespace) {
        continue;
      }
      switch (nodeName) {
        case 'select':
          phase = _inSelectPhase;
          return;
        case 'td':
          phase = _inCellPhase;
          return;
        case 'th':
          phase = _inCellPhase;
          return;
        case 'tr':
          phase = _inRowPhase;
          return;
        case 'tbody':
          phase = _inTableBodyPhase;
          return;
        case 'thead':
          phase = _inTableBodyPhase;
          return;
        case 'tfoot':
          phase = _inTableBodyPhase;
          return;
        case 'caption':
          phase = _inCaptionPhase;
          return;
        case 'colgroup':
          phase = _inColumnGroupPhase;
          return;
        case 'table':
          phase = _inTablePhase;
          return;
        case 'head':
          phase = _inBodyPhase;
          return;
        case 'body':
          phase = _inBodyPhase;
          return;
        case 'frameset':
          phase = _inFramesetPhase;
          return;
        case 'html':
          phase = _beforeHeadPhase;
          return;
      }
    }
    phase = _inBodyPhase;
  }

  /// Generic RCDATA/RAWTEXT Parsing algorithm
  /// [contentType] - RCDATA or RAWTEXT
  void parseRCDataRawtext(Token token, String contentType) {
    assert(contentType == 'RAWTEXT' || contentType == 'RCDATA');

    tree.insertElement(token as StartTagToken);

    if (contentType == 'RAWTEXT') {
      tokenizer.state = tokenizer.rawtextState;
    } else {
      tokenizer.state = tokenizer.rcdataState;
    }

    originalPhase = phase;
    phase = _textPhase;
  }
}

/// Base class for helper object that implements each phase of processing.
class Phase {
  // Order should be (they can be omitted):
  // * EOF
  // * Comment
  // * Doctype
  // * SpaceCharacters
  // * Characters
  // * StartTag
  //   - startTag* methods
  // * EndTag
  //   - endTag* methods

  final HtmlParser parser;

  final TreeBuilder tree;

  Phase(this.parser) : tree = parser.tree;

  bool processEOF() {
    throw UnimplementedError();
  }

  Token? processComment(CommentToken token) {
    // For most phases the following is correct. Where it's not it will be
    // overridden.
    tree.insertComment(token, tree.openElements.last);
    return null;
  }

  Token? processDoctype(DoctypeToken token) {
    parser.parseError(token.span, 'unexpected-doctype');
    return null;
  }

  Token? processCharacters(CharactersToken token) {
    tree.insertText(token.data, token.span);
    return null;
  }

  Token? processSpaceCharacters(SpaceCharactersToken token) {
    tree.insertText(token.data, token.span);
    return null;
  }

  Token? processStartTag(StartTagToken token) {
    throw UnimplementedError();
  }

  Token? startTagHtml(StartTagToken token) {
    if (parser.firstStartTag == false && token.name == 'html') {
      parser.parseError(token.span, 'non-html-root');
    }
    // XXX Need a check here to see if the first start tag token emitted is
    // this token... If it's not, invoke parser.parseError().
    tree.openElements[0].sourceSpan = token.span;
    token.data.forEach((attr, value) {
      tree.openElements[0].attributes.putIfAbsent(attr, () => value);
    });
    parser.firstStartTag = false;
    return null;
  }

  Token? processEndTag(EndTagToken token) {
    throw UnimplementedError();
  }

  /// Helper method for popping openElements.
  void popOpenElementsUntil(EndTagToken token) {
    final name = token.name;
    var node = tree.openElements.removeLast();
    while (node.localName != name) {
      node = tree.openElements.removeLast();
    }
    node.endSourceSpan = token.span;
  }
}

class InitialPhase extends Phase {
  InitialPhase(super.parser);

  @override
  Token? processSpaceCharacters(SpaceCharactersToken token) {
    return null;
  }

  @override
  Token? processComment(CommentToken token) {
    tree.insertComment(token, tree.document);
    return null;
  }

  @override
  Token? processDoctype(DoctypeToken token) {
    final name = token.name;
    var publicId = token.publicId?.toAsciiLowerCase();
    final systemId = token.systemId;
    final correct = token.correct;

    if (name != 'html' ||
        publicId != null ||
        systemId != null && systemId != 'about:legacy-compat') {
      parser.parseError(token.span, 'unknown-doctype');
    }

    publicId ??= '';

    tree.insertDoctype(token);

    if (!correct ||
        token.name != 'html' ||
        startsWithAny(publicId, const [
          '+//silmaril//dtd html pro v0r11 19970101//',
          '-//advasoft ltd//dtd html 3.0 aswedit + extensions//',
          '-//as//dtd html 3.0 aswedit + extensions//',
          '-//ietf//dtd html 2.0 level 1//',
          '-//ietf//dtd html 2.0 level 2//',
          '-//ietf//dtd html 2.0 strict level 1//',
          '-//ietf//dtd html 2.0 strict level 2//',
          '-//ietf//dtd html 2.0 strict//',
          '-//ietf//dtd html 2.0//',
          '-//ietf//dtd html 2.1e//',
          '-//ietf//dtd html 3.0//',
          '-//ietf//dtd html 3.2 final//',
          '-//ietf//dtd html 3.2//',
          '-//ietf//dtd html 3//',
          '-//ietf//dtd html level 0//',
          '-//ietf//dtd html level 1//',
          '-//ietf//dtd html level 2//',
          '-//ietf//dtd html level 3//',
          '-//ietf//dtd html strict level 0//',
          '-//ietf//dtd html strict level 1//',
          '-//ietf//dtd html strict level 2//',
          '-//ietf//dtd html strict level 3//',
          '-//ietf//dtd html strict//',
          '-//ietf//dtd html//',
          '-//metrius//dtd metrius presentational//',
          '-//microsoft//dtd internet explorer 2.0 html strict//',
          '-//microsoft//dtd internet explorer 2.0 html//',
          '-//microsoft//dtd internet explorer 2.0 tables//',
          '-//microsoft//dtd internet explorer 3.0 html strict//',
          '-//microsoft//dtd internet explorer 3.0 html//',
          '-//microsoft//dtd internet explorer 3.0 tables//',
          '-//netscape comm. corp.//dtd html//',
          '-//netscape comm. corp.//dtd strict html//',
          "-//o'reilly and associates//dtd html 2.0//",
          "-//o'reilly and associates//dtd html extended 1.0//",
          "-//o'reilly and associates//dtd html extended relaxed 1.0//",
          '-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//',
          '-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//',
          '-//spyglass//dtd html 2.0 extended//',
          '-//sq//dtd html 2.0 hotmetal + extensions//',
          '-//sun microsystems corp.//dtd hotjava html//',
          '-//sun microsystems corp.//dtd hotjava strict html//',
          '-//w3c//dtd html 3 1995-03-24//',
          '-//w3c//dtd html 3.2 draft//',
          '-//w3c//dtd html 3.2 final//',
          '-//w3c//dtd html 3.2//',
          '-//w3c//dtd html 3.2s draft//',
          '-//w3c//dtd html 4.0 frameset//',
          '-//w3c//dtd html 4.0 transitional//',
          '-//w3c//dtd html experimental 19960712//',
          '-//w3c//dtd html experimental 970421//',
          '-//w3c//dtd w3 html//',
          '-//w3o//dtd w3 html 3.0//',
          '-//webtechs//dtd mozilla html 2.0//',
          '-//webtechs//dtd mozilla html//'
        ]) ||
        const [
          '-//w3o//dtd w3 html strict 3.0//en//',
          '-/w3c/dtd html 4.0 transitional/en',
          'html'
        ].contains(publicId) ||
        startsWithAny(publicId, const [
              '-//w3c//dtd html 4.01 frameset//',
              '-//w3c//dtd html 4.01 transitional//'
            ]) &&
            systemId == null ||
        systemId != null &&
            systemId.toLowerCase() ==
                'http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd') {
      parser.compatMode = 'quirks';
    } else if (startsWithAny(publicId, const [
          '-//w3c//dtd xhtml 1.0 frameset//',
          '-//w3c//dtd xhtml 1.0 transitional//'
        ]) ||
        startsWithAny(publicId, const [
              '-//w3c//dtd html 4.01 frameset//',
              '-//w3c//dtd html 4.01 transitional//'
            ]) &&
            systemId != null) {
      parser.compatMode = 'limited quirks';
    }
    parser.phase = parser._beforeHtmlPhase;
    return null;
  }

  void anythingElse() {
    parser.compatMode = 'quirks';
    parser.phase = parser._beforeHtmlPhase;
  }

  @override
  Token processCharacters(CharactersToken token) {
    parser.parseError(token.span, 'expected-doctype-but-got-chars');
    anythingElse();
    return token;
  }

  @override
  Token processStartTag(StartTagToken token) {
    parser.parseError(
        token.span, 'expected-doctype-but-got-start-tag', {'name': token.name});
    anythingElse();
    return token;
  }

  @override
  Token processEndTag(EndTagToken token) {
    parser.parseError(
        token.span, 'expected-doctype-but-got-end-tag', {'name': token.name});
    anythingElse();
    return token;
  }

  @override
  bool processEOF() {
    parser.parseError(parser._lastSpan, 'expected-doctype-but-got-eof');
    anythingElse();
    return true;
  }
}

class BeforeHtmlPhase extends Phase {
  BeforeHtmlPhase(super.parser);

  // helper methods
  void insertHtmlElement() {
    tree.insertRoot(
        StartTagToken('html', data: LinkedHashMap<Object, String>()));
    parser.phase = parser._beforeHeadPhase;
  }

  // other
  @override
  bool processEOF() {
    insertHtmlElement();
    return true;
  }

  @override
  Token? processComment(CommentToken token) {
    tree.insertComment(token, tree.document);
    return null;
  }

  @override
  Token? processSpaceCharacters(SpaceCharactersToken token) {
    return null;
  }

  @override
  Token processCharacters(CharactersToken token) {
    insertHtmlElement();
    return token;
  }

  @override
  @override
  Token processStartTag(StartTagToken token) {
    if (token.name == 'html') {
      parser.firstStartTag = true;
    }
    insertHtmlElement();
    return token;
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'head':
      case 'body':
      case 'html':
      case 'br':
        insertHtmlElement();
        return token;
      default:
        parser.parseError(
            token.span, 'unexpected-end-tag-before-html', {'name': token.name});
        return null;
    }
  }
}

class BeforeHeadPhase extends Phase {
  BeforeHeadPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'head':
        startTagHead(token);
        return null;
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'head':
      case 'body':
      case 'html':
      case 'br':
        return endTagImplyHead(token);
      default:
        endTagOther(token);
        return null;
    }
  }

  @override
  bool processEOF() {
    startTagHead(StartTagToken('head', data: LinkedHashMap<Object, String>()));
    return true;
  }

  @override
  Token? processSpaceCharacters(SpaceCharactersToken token) {
    return null;
  }

  @override
  Token processCharacters(CharactersToken token) {
    startTagHead(StartTagToken('head', data: LinkedHashMap<Object, String>()));
    return token;
  }

  @override
  Token? startTagHtml(StartTagToken token) {
    return parser._inBodyPhase.processStartTag(token);
  }

  void startTagHead(StartTagToken token) {
    tree.insertElement(token);
    tree.headPointer = tree.openElements.last;
    parser.phase = parser._inHeadPhase;
  }

  Token startTagOther(StartTagToken token) {
    startTagHead(StartTagToken('head', data: LinkedHashMap<Object, String>()));
    return token;
  }

  Token endTagImplyHead(EndTagToken token) {
    startTagHead(StartTagToken('head', data: LinkedHashMap<Object, String>()));
    return token;
  }

  void endTagOther(EndTagToken token) {
    parser.parseError(
        token.span, 'end-tag-after-implied-root', {'name': token.name});
  }
}

class InHeadPhase extends Phase {
  InHeadPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'title':
        startTagTitle(token);
        return null;
      case 'noscript':
      case 'noframes':
      case 'style':
        startTagNoScriptNoFramesStyle(token);
        return null;
      case 'script':
        startTagScript(token);
        return null;
      case 'base':
      case 'basefont':
      case 'bgsound':
      case 'command':
      case 'link':
        startTagBaseLinkCommand(token);
        return null;
      case 'meta':
        startTagMeta(token);
        return null;
      case 'head':
        startTagHead(token);
        return null;
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'head':
        endTagHead(token);
        return null;
      case 'br':
      case 'html':
      case 'body':
        return endTagHtmlBodyBr(token);
      default:
        endTagOther(token);
        return null;
    }
  }

  // the real thing
  @override
  bool processEOF() {
    anythingElse();
    return true;
  }

  @override
  Token processCharacters(CharactersToken token) {
    anythingElse();
    return token;
  }

  @override
  Token? startTagHtml(StartTagToken token) {
    return parser._inBodyPhase.processStartTag(token);
  }

  void startTagHead(StartTagToken token) {
    parser.parseError(token.span, 'two-heads-are-not-better-than-one');
  }

  void startTagBaseLinkCommand(StartTagToken token) {
    tree.insertElement(token);
    tree.openElements.removeLast();
    token.selfClosingAcknowledged = true;
  }

  void startTagMeta(StartTagToken token) {
    tree.insertElement(token);
    tree.openElements.removeLast();
    token.selfClosingAcknowledged = true;

    final attributes = token.data;
    if (!parser.tokenizer.stream.charEncodingCertain) {
      final charset = attributes['charset'];
      final content = attributes['content'];
      if (charset != null) {
        parser.tokenizer.stream.changeEncoding(charset);
      } else if (content != null) {
        final data = EncodingBytes(content);
        final codec = ContentAttrParser(data).parse();
        parser.tokenizer.stream.changeEncoding(codec);
      }
    }
  }

  void startTagTitle(StartTagToken token) {
    parser.parseRCDataRawtext(token, 'RCDATA');
  }

  void startTagNoScriptNoFramesStyle(StartTagToken token) {
    // Need to decide whether to implement the scripting-disabled case
    parser.parseRCDataRawtext(token, 'RAWTEXT');
  }

  void startTagScript(StartTagToken token) {
    tree.insertElement(token);
    parser.tokenizer.state = parser.tokenizer.scriptDataState;
    parser.originalPhase = parser.phase;
    parser.phase = parser._textPhase;
  }

  Token startTagOther(StartTagToken token) {
    anythingElse();
    return token;
  }

  void endTagHead(EndTagToken token) {
    final node = parser.tree.openElements.removeLast();
    assert(node.localName == 'head');
    node.endSourceSpan = token.span;
    parser.phase = parser._afterHeadPhase;
  }

  Token endTagHtmlBodyBr(EndTagToken token) {
    anythingElse();
    return token;
  }

  void endTagOther(EndTagToken token) {
    parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name});
  }

  void anythingElse() {
    endTagHead(EndTagToken('head'));
  }
}

// XXX If we implement a parser for which scripting is disabled we need to
// implement this phase.
//
// class InHeadNoScriptPhase extends Phase {

class AfterHeadPhase extends Phase {
  AfterHeadPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'body':
        startTagBody(token);
        return null;
      case 'frameset':
        startTagFrameset(token);
        return null;
      case 'base':
      case 'basefont':
      case 'bgsound':
      case 'link':
      case 'meta':
      case 'noframes':
      case 'script':
      case 'style':
      case 'title':
        startTagFromHead(token);
        return null;
      case 'head':
        startTagHead(token);
        return null;
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'body':
      case 'html':
      case 'br':
        return endTagHtmlBodyBr(token);
      default:
        endTagOther(token);
        return null;
    }
  }

  @override
  bool processEOF() {
    anythingElse();
    return true;
  }

  @override
  Token processCharacters(CharactersToken token) {
    anythingElse();
    return token;
  }

  @override
  Token? startTagHtml(StartTagToken token) {
    return parser._inBodyPhase.processStartTag(token);
  }

  void startTagBody(StartTagToken token) {
    parser.framesetOK = false;
    tree.insertElement(token);
    parser.phase = parser._inBodyPhase;
  }

  void startTagFrameset(StartTagToken token) {
    tree.insertElement(token);
    parser.phase = parser._inFramesetPhase;
  }

  void startTagFromHead(StartTagToken token) {
    parser.parseError(token.span, 'unexpected-start-tag-out-of-my-head',
        {'name': token.name});
    tree.openElements.add(tree.headPointer as Element);
    parser._inHeadPhase.processStartTag(token);
    for (var node in tree.openElements.reversed) {
      if (node.localName == 'head') {
        tree.openElements.remove(node);
        break;
      }
    }
  }

  void startTagHead(StartTagToken token) {
    parser.parseError(token.span, 'unexpected-start-tag', {'name': token.name});
  }

  Token startTagOther(StartTagToken token) {
    anythingElse();
    return token;
  }

  Token endTagHtmlBodyBr(EndTagToken token) {
    anythingElse();
    return token;
  }

  void endTagOther(EndTagToken token) {
    parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name});
  }

  void anythingElse() {
    tree.insertElement(
        StartTagToken('body', data: LinkedHashMap<Object, String>()));
    parser.phase = parser._inBodyPhase;
    parser.framesetOK = true;
  }
}

typedef TokenProccessor = Token Function(Token token);

class InBodyPhase extends Phase {
  bool dropNewline = false;

  // http://www.whatwg.org/specs/web-apps/current-work///parsing-main-inbody
  // the really-really-really-very crazy mode
  InBodyPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'base':
      case 'basefont':
      case 'bgsound':
      case 'command':
      case 'link':
      case 'meta':
      case 'noframes':
      case 'script':
      case 'style':
      case 'title':
        return startTagProcessInHead(token);
      case 'body':
        startTagBody(token);
        return null;
      case 'frameset':
        startTagFrameset(token);
        return null;
      case 'address':
      case 'article':
      case 'aside':
      case 'blockquote':
      case 'center':
      case 'details':
      case 'dir':
      case 'div':
      case 'dl':
      case 'fieldset':
      case 'figcaption':
      case 'figure':
      case 'footer':
      case 'header':
      case 'hgroup':
      case 'menu':
      case 'nav':
      case 'ol':
      case 'p':
      case 'section':
      case 'summary':
      case 'ul':
        startTagCloseP(token);
        return null;
      // headingElements
      case 'h1':
      case 'h2':
      case 'h3':
      case 'h4':
      case 'h5':
      case 'h6':
        startTagHeading(token);
        return null;
      case 'pre':
      case 'listing':
        startTagPreListing(token);
        return null;
      case 'form':
        startTagForm(token);
        return null;
      case 'li':
      case 'dd':
      case 'dt':
        startTagListItem(token);
        return null;
      case 'plaintext':
        startTagPlaintext(token);
        return null;
      case 'a':
        startTagA(token);
        return null;
      case 'b':
      case 'big':
      case 'code':
      case 'em':
      case 'font':
      case 'i':
      case 's':
      case 'small':
      case 'strike':
      case 'strong':
      case 'tt':
      case 'u':
        startTagFormatting(token);
        return null;
      case 'nobr':
        startTagNobr(token);
        return null;
      case 'button':
        return startTagButton(token);
      case 'applet':
      case 'marquee':
      case 'object':
        startTagAppletMarqueeObject(token);
        return null;
      case 'xmp':
        startTagXmp(token);
        return null;
      case 'table':
        startTagTable(token);
        return null;
      case 'area':
      case 'br':
      case 'embed':
      case 'img':
      case 'keygen':
      case 'wbr':
        startTagVoidFormatting(token);
        return null;
      case 'param':
      case 'source':
      case 'track':
        startTagParamSource(token);
        return null;
      case 'input':
        startTagInput(token);
        return null;
      case 'hr':
        startTagHr(token);
        return null;
      case 'image':
        startTagImage(token);
        return null;
      case 'isindex':
        startTagIsIndex(token);
        return null;
      case 'textarea':
        startTagTextarea(token);
        return null;
      case 'iframe':
        startTagIFrame(token);
        return null;
      case 'noembed':
      case 'noscript':
        startTagRawtext(token);
        return null;
      case 'select':
        startTagSelect(token);
        return null;
      case 'rp':
      case 'rt':
        startTagRpRt(token);
        return null;
      case 'option':
      case 'optgroup':
        startTagOpt(token);
        return null;
      case 'math':
        startTagMath(token);
        return null;
      case 'svg':
        startTagSvg(token);
        return null;
      case 'caption':
      case 'col':
      case 'colgroup':
      case 'frame':
      case 'head':
      case 'tbody':
      case 'td':
      case 'tfoot':
      case 'th':
      case 'thead':
      case 'tr':
        startTagMisplaced(token);
        return null;
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'body':
        endTagBody(token);
        return null;
      case 'html':
        return endTagHtml(token);
      case 'address':
      case 'article':
      case 'aside':
      case 'blockquote':
      case 'button':
      case 'center':
      case 'details':
      case 'dir':
      case 'div':
      case 'dl':
      case 'fieldset':
      case 'figcaption':
      case 'figure':
      case 'footer':
      case 'header':
      case 'hgroup':
      case 'listing':
      case 'menu':
      case 'nav':
      case 'ol':
      case 'pre':
      case 'section':
      case 'summary':
      case 'ul':
        endTagBlock(token);
        return null;
      case 'form':
        endTagForm(token);
        return null;
      case 'p':
        endTagP(token);
        return null;
      case 'dd':
      case 'dt':
      case 'li':
        endTagListItem(token);
        return null;
      // headingElements
      case 'h1':
      case 'h2':
      case 'h3':
      case 'h4':
      case 'h5':
      case 'h6':
        endTagHeading(token);
        return null;
      case 'a':
      case 'b':
      case 'big':
      case 'code':
      case 'em':
      case 'font':
      case 'i':
      case 'nobr':
      case 's':
      case 'small':
      case 'strike':
      case 'strong':
      case 'tt':
      case 'u':
        endTagFormatting(token);
        return null;
      case 'applet':
      case 'marquee':
      case 'object':
        endTagAppletMarqueeObject(token);
        return null;
      case 'br':
        endTagBr(token);
        return null;
      default:
        endTagOther(token);
        return null;
    }
  }

  bool isMatchingFormattingElement(Element node1, Element node2) {
    if (node1.localName != node2.localName ||
        node1.namespaceUri != node2.namespaceUri) {
      return false;
    } else if (node1.attributes.length != node2.attributes.length) {
      return false;
    } else {
      for (var key in node1.attributes.keys) {
        if (node1.attributes[key] != node2.attributes[key]) {
          return false;
        }
      }
    }
    return true;
  }

  // helper
  void addFormattingElement(StartTagToken token) {
    tree.insertElement(token);
    final element = tree.openElements.last;

    final matchingElements = <Node?>[];
    for (Node? node in tree.activeFormattingElements.reversed) {
      if (node == null) {
        break;
      } else if (isMatchingFormattingElement(node as Element, element)) {
        matchingElements.add(node);
      }
    }

    assert(matchingElements.length <= 3);
    if (matchingElements.length == 3) {
      tree.activeFormattingElements.remove(matchingElements.last);
    }
    tree.activeFormattingElements.add(element);
  }

  // the real deal
  @override
  bool processEOF() {
    for (var node in tree.openElements.reversed) {
      switch (node.localName) {
        case 'dd':
        case 'dt':
        case 'li':
        case 'p':
        case 'tbody':
        case 'td':
        case 'tfoot':
        case 'th':
        case 'thead':
        case 'tr':
        case 'body':
        case 'html':
          continue;
      }
      parser.parseError(node.sourceSpan, 'expected-closing-tag-but-got-eof');
      break;
    }
    //Stop parsing
    return false;
  }

  void processSpaceCharactersDropNewline(StringToken token) {
    // Sometimes (start of <pre>, <listing>, and <textarea> blocks) we
    // want to drop leading newlines
    var data = token.data;
    dropNewline = false;
    if (data.startsWith('\n')) {
      final lastOpen = tree.openElements.last;
      if (const ['pre', 'listing', 'textarea'].contains(lastOpen.localName) &&
          !lastOpen.hasContent()) {
        data = data.substring(1);
      }
    }
    if (data.isNotEmpty) {
      tree.reconstructActiveFormattingElements();
      tree.insertText(data, token.span);
    }
  }

  @override
  Token? processCharacters(CharactersToken token) {
    if (token.data == '\u0000') {
      //The tokenizer should always emit null on its own
      return null;
    }
    tree.reconstructActiveFormattingElements();
    tree.insertText(token.data, token.span);
    if (parser.framesetOK && !allWhitespace(token.data)) {
      parser.framesetOK = false;
    }
    return null;
  }

  @override
  Token? processSpaceCharacters(SpaceCharactersToken token) {
    if (dropNewline) {
      processSpaceCharactersDropNewline(token);
    } else {
      tree.reconstructActiveFormattingElements();
      tree.insertText(token.data, token.span);
    }
    return null;
  }

  Token? startTagProcessInHead(StartTagToken token) {
    return parser._inHeadPhase.processStartTag(token);
  }

  void startTagBody(StartTagToken token) {
    parser.parseError(token.span, 'unexpected-start-tag', {'name': 'body'});
    if (tree.openElements.length == 1 ||
        tree.openElements[1].localName != 'body') {
      assert(parser.innerHTMLMode);
    } else {
      parser.framesetOK = false;
      token.data.forEach((attr, value) {
        tree.openElements[1].attributes.putIfAbsent(attr, () => value);
      });
    }
  }

  void startTagFrameset(StartTagToken token) {
    parser.parseError(token.span, 'unexpected-start-tag', {'name': 'frameset'});
    if (tree.openElements.length == 1 ||
        tree.openElements[1].localName != 'body') {
      assert(parser.innerHTMLMode);
    } else if (parser.framesetOK) {
      if (tree.openElements[1].parentNode != null) {
        tree.openElements[1].parentNode!.nodes.remove(tree.openElements[1]);
      }
      while (tree.openElements.last.localName != 'html') {
        tree.openElements.removeLast();
      }
      tree.insertElement(token);
      parser.phase = parser._inFramesetPhase;
    }
  }

  void startTagCloseP(StartTagToken token) {
    if (tree.elementInScope('p', variant: 'button')) {
      endTagP(EndTagToken('p'));
    }
    tree.insertElement(token);
  }

  void startTagPreListing(StartTagToken token) {
    if (tree.elementInScope('p', variant: 'button')) {
      endTagP(EndTagToken('p'));
    }
    tree.insertElement(token);
    parser.framesetOK = false;
    dropNewline = true;
  }

  void startTagForm(StartTagToken token) {
    if (tree.formPointer != null) {
      parser.parseError(token.span, 'unexpected-start-tag', {'name': 'form'});
    } else {
      if (tree.elementInScope('p', variant: 'button')) {
        endTagP(EndTagToken('p'));
      }
      tree.insertElement(token);
      tree.formPointer = tree.openElements.last;
    }
  }

  void startTagListItem(StartTagToken token) {
    parser.framesetOK = false;

    final stopNamesMap = const {
      'li': ['li'],
      'dt': ['dt', 'dd'],
      'dd': ['dt', 'dd']
    };
    final stopNames = stopNamesMap[token.name!]!;
    for (var node in tree.openElements.reversed) {
      if (stopNames.contains(node.localName)) {
        parser.phase.processEndTag(EndTagToken(node.localName));
        break;
      }
      if (specialElements.contains(getElementNameTuple(node)) &&
          !const ['address', 'div', 'p'].contains(node.localName)) {
        break;
      }
    }

    if (tree.elementInScope('p', variant: 'button')) {
      parser.phase.processEndTag(EndTagToken('p'));
    }

    tree.insertElement(token);
  }

  void startTagPlaintext(StartTagToken token) {
    if (tree.elementInScope('p', variant: 'button')) {
      endTagP(EndTagToken('p'));
    }
    tree.insertElement(token);
    parser.tokenizer.state = parser.tokenizer.plaintextState;
  }

  void startTagHeading(StartTagToken token) {
    if (tree.elementInScope('p', variant: 'button')) {
      endTagP(EndTagToken('p'));
    }
    if (headingElements.contains(tree.openElements.last.localName)) {
      parser
          .parseError(token.span, 'unexpected-start-tag', {'name': token.name});
      tree.openElements.removeLast();
    }
    tree.insertElement(token);
  }

  void startTagA(StartTagToken token) {
    final afeAElement = tree.elementInActiveFormattingElements('a');
    if (afeAElement != null) {
      parser.parseError(token.span, 'unexpected-start-tag-implies-end-tag',
          {'startName': 'a', 'endName': 'a'});
      endTagFormatting(EndTagToken('a'));
      tree.openElements.remove(afeAElement);
      tree.activeFormattingElements.remove(afeAElement);
    }
    tree.reconstructActiveFormattingElements();
    addFormattingElement(token);
  }

  void startTagFormatting(StartTagToken token) {
    tree.reconstructActiveFormattingElements();
    addFormattingElement(token);
  }

  void startTagNobr(StartTagToken token) {
    tree.reconstructActiveFormattingElements();
    if (tree.elementInScope('nobr')) {
      parser.parseError(token.span, 'unexpected-start-tag-implies-end-tag',
          {'startName': 'nobr', 'endName': 'nobr'});
      processEndTag(EndTagToken('nobr'));
      // XXX Need tests that trigger the following
      tree.reconstructActiveFormattingElements();
    }
    addFormattingElement(token);
  }

  Token? startTagButton(StartTagToken token) {
    if (tree.elementInScope('button')) {
      parser.parseError(token.span, 'unexpected-start-tag-implies-end-tag',
          {'startName': 'button', 'endName': 'button'});
      processEndTag(EndTagToken('button'));
      return token;
    } else {
      tree.reconstructActiveFormattingElements();
      tree.insertElement(token);
      parser.framesetOK = false;
    }
    return null;
  }

  void startTagAppletMarqueeObject(StartTagToken token) {
    tree.reconstructActiveFormattingElements();
    tree.insertElement(token);
    tree.activeFormattingElements.add(null);
    parser.framesetOK = false;
  }

  void startTagXmp(StartTagToken token) {
    if (tree.elementInScope('p', variant: 'button')) {
      endTagP(EndTagToken('p'));
    }
    tree.reconstructActiveFormattingElements();
    parser.framesetOK = false;
    parser.parseRCDataRawtext(token, 'RAWTEXT');
  }

  void startTagTable(StartTagToken token) {
    if (parser.compatMode != 'quirks') {
      if (tree.elementInScope('p', variant: 'button')) {
        processEndTag(EndTagToken('p'));
      }
    }
    tree.insertElement(token);
    parser.framesetOK = false;
    parser.phase = parser._inTablePhase;
  }

  void startTagVoidFormatting(StartTagToken token) {
    tree.reconstructActiveFormattingElements();
    tree.insertElement(token);
    tree.openElements.removeLast();
    token.selfClosingAcknowledged = true;
    parser.framesetOK = false;
  }

  void startTagInput(StartTagToken token) {
    final savedFramesetOK = parser.framesetOK;
    startTagVoidFormatting(token);
    if (token.data['type']?.toAsciiLowerCase() == 'hidden') {
      //input type=hidden doesn't change framesetOK
      parser.framesetOK = savedFramesetOK;
    }
  }

  void startTagParamSource(StartTagToken token) {
    tree.insertElement(token);
    tree.openElements.removeLast();
    token.selfClosingAcknowledged = true;
  }

  void startTagHr(StartTagToken token) {
    if (tree.elementInScope('p', variant: 'button')) {
      endTagP(EndTagToken('p'));
    }
    tree.insertElement(token);
    tree.openElements.removeLast();
    token.selfClosingAcknowledged = true;
    parser.framesetOK = false;
  }

  void startTagImage(StartTagToken token) {
    // No really...
    parser.parseError(token.span, 'unexpected-start-tag-treated-as',
        {'originalName': 'image', 'newName': 'img'});
    processStartTag(
        StartTagToken('img', data: token.data, selfClosing: token.selfClosing));
  }

  void startTagIsIndex(StartTagToken token) {
    parser.parseError(token.span, 'deprecated-tag', {'name': 'isindex'});
    if (tree.formPointer != null) {
      return;
    }
    final formAttrs = LinkedHashMap<Object, String>();
    final dataAction = token.data['action'];
    if (dataAction != null) {
      formAttrs['action'] = dataAction;
    }
    processStartTag(StartTagToken('form', data: formAttrs));
    processStartTag(StartTagToken('hr', data: LinkedHashMap<Object, String>()));
    processStartTag(
        StartTagToken('label', data: LinkedHashMap<Object, String>()));
    // XXX Localization ...
    var prompt = token.data['prompt'];
    prompt ??= 'This is a searchable index. Enter search keywords: ';
    processCharacters(CharactersToken(prompt));
    final attributes = LinkedHashMap<Object, String>.from(token.data);
    attributes.remove('action');
    attributes.remove('prompt');
    attributes['name'] = 'isindex';
    processStartTag(StartTagToken('input',
        data: attributes, selfClosing: token.selfClosing));
    processEndTag(EndTagToken('label'));
    processStartTag(StartTagToken('hr', data: LinkedHashMap<Object, String>()));
    processEndTag(EndTagToken('form'));
  }

  void startTagTextarea(StartTagToken token) {
    tree.insertElement(token);
    parser.tokenizer.state = parser.tokenizer.rcdataState;
    dropNewline = true;
    parser.framesetOK = false;
  }

  void startTagIFrame(StartTagToken token) {
    parser.framesetOK = false;
    startTagRawtext(token);
  }

  /// iframe, noembed noframes, noscript(if scripting enabled).
  void startTagRawtext(StartTagToken token) {
    parser.parseRCDataRawtext(token, 'RAWTEXT');
  }

  void startTagOpt(StartTagToken token) {
    if (tree.openElements.last.localName == 'option') {
      parser.phase.processEndTag(EndTagToken('option'));
    }
    tree.reconstructActiveFormattingElements();
    parser.tree.insertElement(token);
  }

  void startTagSelect(StartTagToken token) {
    tree.reconstructActiveFormattingElements();
    tree.insertElement(token);
    parser.framesetOK = false;

    if (parser._inTablePhase == parser.phase ||
        parser._inCaptionPhase == parser.phase ||
        parser._inColumnGroupPhase == parser.phase ||
        parser._inTableBodyPhase == parser.phase ||
        parser._inRowPhase == parser.phase ||
        parser._inCellPhase == parser.phase) {
      parser.phase = parser._inSelectInTablePhase;
    } else {
      parser.phase = parser._inSelectPhase;
    }
  }

  void startTagRpRt(StartTagToken token) {
    if (tree.elementInScope('ruby')) {
      tree.generateImpliedEndTags();
      final last = tree.openElements.last;
      if (last.localName != 'ruby') {
        parser.parseError(last.sourceSpan, 'undefined-error');
      }
    }
    tree.insertElement(token);
  }

  void startTagMath(StartTagToken token) {
    tree.reconstructActiveFormattingElements();
    parser.adjustMathMLAttributes(token);
    parser.adjustForeignAttributes(token);
    token.namespace = Namespaces.mathml;
    tree.insertElement(token);
    //Need to get the parse error right for the case where the token
    //has a namespace not equal to the xmlns attribute
    if (token.selfClosing) {
      tree.openElements.removeLast();
      token.selfClosingAcknowledged = true;
    }
  }

  void startTagSvg(StartTagToken token) {
    tree.reconstructActiveFormattingElements();
    parser.adjustSVGAttributes(token);
    parser.adjustForeignAttributes(token);
    token.namespace = Namespaces.svg;
    tree.insertElement(token);
    //Need to get the parse error right for the case where the token
    //has a namespace not equal to the xmlns attribute
    if (token.selfClosing) {
      tree.openElements.removeLast();
      token.selfClosingAcknowledged = true;
    }
  }

  /// Elements that should be children of other elements that have a
  /// different insertion mode; here they are ignored
  /// "caption", "col", "colgroup", "frame", "frameset", "head",
  /// "option", "optgroup", "tbody", "td", "tfoot", "th", "thead",
  /// "tr", "noscript"
  void startTagMisplaced(StartTagToken token) {
    parser.parseError(
        token.span, 'unexpected-start-tag-ignored', {'name': token.name});
  }

  Token? startTagOther(StartTagToken token) {
    tree.reconstructActiveFormattingElements();
    tree.insertElement(token);
    return null;
  }

  void endTagP(EndTagToken token) {
    if (!tree.elementInScope('p', variant: 'button')) {
      startTagCloseP(StartTagToken('p', data: LinkedHashMap<Object, String>()));
      parser.parseError(token.span, 'unexpected-end-tag', {'name': 'p'});
      endTagP(EndTagToken('p'));
    } else {
      tree.generateImpliedEndTags('p');
      if (tree.openElements.last.localName != 'p') {
        parser.parseError(token.span, 'unexpected-end-tag', {'name': 'p'});
      }
      popOpenElementsUntil(token);
    }
  }

  void endTagBody(EndTagToken token) {
    if (!tree.elementInScope('body')) {
      parser.parseError(token.span, 'undefined-error');
      return;
    } else if (tree.openElements.last.localName == 'body') {
      tree.openElements.last.endSourceSpan = token.span;
    } else {
      for (var node in slice(tree.openElements, 2)) {
        switch (node.localName) {
          case 'dd':
          case 'dt':
          case 'li':
          case 'optgroup':
          case 'option':
          case 'p':
          case 'rp':
          case 'rt':
          case 'tbody':
          case 'td':
          case 'tfoot':
          case 'th':
          case 'thead':
          case 'tr':
          case 'body':
          case 'html':
            continue;
        }
        // Not sure this is the correct name for the parse error
        parser.parseError(token.span, 'expected-one-end-tag-but-got-another',
            {'gotName': 'body', 'expectedName': node.localName});
        break;
      }
    }
    parser.phase = parser._afterBodyPhase;
  }

  Token? endTagHtml(EndTagToken token) {
    //We repeat the test for the body end tag token being ignored here
    if (tree.elementInScope('body')) {
      endTagBody(EndTagToken('body'));
      return token;
    }
    return null;
  }

  void endTagBlock(EndTagToken token) {
    //Put us back in the right whitespace handling mode
    if (token.name == 'pre') {
      dropNewline = false;
    }
    final inScope = tree.elementInScope(token.name);
    if (inScope) {
      tree.generateImpliedEndTags();
    }
    if (tree.openElements.last.localName != token.name) {
      parser.parseError(token.span, 'end-tag-too-early', {'name': token.name});
    }
    if (inScope) {
      popOpenElementsUntil(token);
    }
  }

  void endTagForm(EndTagToken token) {
    final node = tree.formPointer;
    tree.formPointer = null;
    if (node == null || !tree.elementInScope(node)) {
      parser.parseError(token.span, 'unexpected-end-tag', {'name': 'form'});
    } else {
      tree.generateImpliedEndTags();
      if (tree.openElements.last != node) {
        parser.parseError(
            token.span, 'end-tag-too-early-ignored', {'name': 'form'});
      }
      tree.openElements.remove(node);
      node.endSourceSpan = token.span;
    }
  }

  void endTagListItem(EndTagToken token) {
    String? variant;
    if (token.name == 'li') {
      variant = 'list';
    } else {
      variant = null;
    }
    if (!tree.elementInScope(token.name, variant: variant)) {
      parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name});
    } else {
      tree.generateImpliedEndTags(token.name);
      if (tree.openElements.last.localName != token.name) {
        parser
            .parseError(token.span, 'end-tag-too-early', {'name': token.name});
      }
      popOpenElementsUntil(token);
    }
  }

  void endTagHeading(EndTagToken token) {
    for (var item in headingElementsList) {
      if (tree.elementInScope(item)) {
        tree.generateImpliedEndTags();
        break;
      }
    }
    if (tree.openElements.last.localName != token.name) {
      parser.parseError(token.span, 'end-tag-too-early', {'name': token.name});
    }

    for (var item in headingElementsList) {
      if (tree.elementInScope(item)) {
        var node = tree.openElements.removeLast();
        while (!headingElements.contains(node.localName)) {
          node = tree.openElements.removeLast();
        }
        node.endSourceSpan = token.span;
        break;
      }
    }
  }

  /// The much-feared adoption agency algorithm.
  void endTagFormatting(EndTagToken token) {
    // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#adoptionAgency
    // TODO(jmesserly): the comments here don't match the numbered steps in the
    // updated spec. This needs a pass over it to verify that it still matches.
    // In particular the html5lib Python code skiped "step 4", I'm not sure why.
    // XXX Better parseError messages appreciated.
    var outerLoopCounter = 0;
    while (outerLoopCounter < 8) {
      outerLoopCounter += 1;

      // Step 1 paragraph 1
      final formattingElement =
          tree.elementInActiveFormattingElements(token.name);
      if (formattingElement == null ||
          (tree.openElements.contains(formattingElement) &&
              !tree.elementInScope(formattingElement.localName))) {
        parser.parseError(
            token.span, 'adoption-agency-1.1', {'name': token.name});
        return;
        // Step 1 paragraph 2
      } else if (!tree.openElements.contains(formattingElement)) {
        parser.parseError(
            token.span, 'adoption-agency-1.2', {'name': token.name});
        tree.activeFormattingElements.remove(formattingElement);
        return;
      }

      // Step 1 paragraph 3
      if (formattingElement != tree.openElements.last) {
        parser.parseError(
            token.span, 'adoption-agency-1.3', {'name': token.name});
      }

      // Step 2
      // Start of the adoption agency algorithm proper
      final afeIndex = tree.openElements.indexOf(formattingElement);
      Element? furthestBlock;
      for (var element in slice(tree.openElements, afeIndex)) {
        if (specialElements.contains(getElementNameTuple(element))) {
          furthestBlock = element;
          break;
        }
      }
      // Step 3
      if (furthestBlock == null) {
        var element = tree.openElements.removeLast();
        while (element != formattingElement) {
          element = tree.openElements.removeLast();
        }
        element.endSourceSpan = token.span;
        tree.activeFormattingElements.remove(element);
        return;
      }

      final commonAncestor = tree.openElements[afeIndex - 1];

      // Step 5
      // The bookmark is supposed to help us identify where to reinsert
      // nodes in step 12. We have to ensure that we reinsert nodes after
      // the node before the active formatting element. Note the bookmark
      // can move in step 7.4
      var bookmark = tree.activeFormattingElements.indexOf(formattingElement);

      // Step 6
      var lastNode = furthestBlock;
      var node = furthestBlock;
      var innerLoopCounter = 0;

      var index = tree.openElements.indexOf(node);
      while (innerLoopCounter < 3) {
        innerLoopCounter += 1;

        // Node is element before node in open elements
        index -= 1;
        node = tree.openElements[index];
        if (!tree.activeFormattingElements.contains(node)) {
          tree.openElements.remove(node);
          continue;
        }
        // Step 6.3
        if (node == formattingElement) {
          break;
        }
        // Step 6.4
        if (lastNode == furthestBlock) {
          bookmark = tree.activeFormattingElements.indexOf(node) + 1;
        }
        // Step 6.5
        //cite = node.parent
        final clone = node.clone(false);
        // Replace node with clone
        tree.activeFormattingElements[
            tree.activeFormattingElements.indexOf(node)] = clone;
        tree.openElements[tree.openElements.indexOf(node)] = clone;
        node = clone;

        // Step 6.6
        // Remove lastNode from its parents, if any
        if (lastNode.parentNode != null) {
          lastNode.parentNode!.nodes.remove(lastNode);
        }
        node.nodes.add(lastNode);
        // Step 7.7
        lastNode = node;
        // End of inner loop
      }

      // Step 7
      // Foster parent lastNode if commonAncestor is a
      // table, tbody, tfoot, thead, or tr we need to foster parent the
      // lastNode
      if (lastNode.parentNode != null) {
        lastNode.parentNode!.nodes.remove(lastNode);
      }

      if (const ['table', 'tbody', 'tfoot', 'thead', 'tr']
          .contains(commonAncestor.localName)) {
        final nodePos = tree.getTableMisnestedNodePosition();
        nodePos[0]!.insertBefore(lastNode, nodePos[1]);
      } else {
        commonAncestor.nodes.add(lastNode);
      }

      // Step 8
      final clone = formattingElement.clone(false);

      // Step 9
      furthestBlock.reparentChildren(clone);

      // Step 10
      furthestBlock.nodes.add(clone);

      // Step 11
      tree.activeFormattingElements.remove(formattingElement);
      tree.activeFormattingElements
          .insert(min(bookmark, tree.activeFormattingElements.length), clone);

      // Step 12
      tree.openElements.remove(formattingElement);
      tree.openElements
          .insert(tree.openElements.indexOf(furthestBlock) + 1, clone);
    }
  }

  void endTagAppletMarqueeObject(EndTagToken token) {
    if (tree.elementInScope(token.name)) {
      tree.generateImpliedEndTags();
    }
    if (tree.openElements.last.localName != token.name) {
      parser.parseError(token.span, 'end-tag-too-early', {'name': token.name});
    }
    if (tree.elementInScope(token.name)) {
      popOpenElementsUntil(token);
      tree.clearActiveFormattingElements();
    }
  }

  void endTagBr(EndTagToken token) {
    parser.parseError(token.span, 'unexpected-end-tag-treated-as',
        {'originalName': 'br', 'newName': 'br element'});
    tree.reconstructActiveFormattingElements();
    tree.insertElement(
        StartTagToken('br', data: LinkedHashMap<Object, String>()));
    tree.openElements.removeLast();
  }

  void endTagOther(EndTagToken token) {
    for (var node in tree.openElements.reversed) {
      if (node.localName == token.name) {
        tree.generateImpliedEndTags(token.name);
        if (tree.openElements.last.localName != token.name) {
          parser.parseError(
              token.span, 'unexpected-end-tag', {'name': token.name});
        }
        while (tree.openElements.removeLast() != node) {
          // noop
        }
        node.endSourceSpan = token.span;
        break;
      } else {
        if (specialElements.contains(getElementNameTuple(node))) {
          parser.parseError(
              token.span, 'unexpected-end-tag', {'name': token.name});
          break;
        }
      }
    }
  }
}

class TextPhase extends Phase {
  TextPhase(super.parser);

  // "Tried to process start tag %s in RCDATA/RAWTEXT mode"%token.name
  @override
  Token processStartTag(StartTagToken token) {
    throw StateError('Cannot process start stag in text phase');
  }

  @override
  Token? processEndTag(EndTagToken token) {
    if (token.name == 'script') {
      endTagScript(token);
      return null;
    }
    endTagOther(token);
    return null;
  }

  @override
  Token? processCharacters(CharactersToken token) {
    tree.insertText(token.data, token.span);
    return null;
  }

  @override
  bool processEOF() {
    final last = tree.openElements.last;
    parser.parseError(last.sourceSpan, 'expected-named-closing-tag-but-got-eof',
        {'name': last.localName});
    tree.openElements.removeLast();
    parser.phase = parser.originalPhase!;
    return true;
  }

  void endTagScript(EndTagToken token) {
    final node = tree.openElements.removeLast();
    assert(node.localName == 'script');
    parser.phase = parser.originalPhase!;
    //The rest of this method is all stuff that only happens if
    //document.write works
  }

  void endTagOther(EndTagToken token) {
    tree.openElements.removeLast();
    parser.phase = parser.originalPhase!;
  }
}

class InTablePhase extends Phase {
  // http://www.whatwg.org/specs/web-apps/current-work///in-table
  InTablePhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'caption':
        startTagCaption(token);
        return null;
      case 'colgroup':
        startTagColgroup(token);
        return null;
      case 'col':
        return startTagCol(token);
      case 'tbody':
      case 'tfoot':
      case 'thead':
        startTagRowGroup(token);
        return null;
      case 'td':
      case 'th':
      case 'tr':
        return startTagImplyTbody(token);
      case 'table':
        return startTagTable(token);
      case 'style':
      case 'script':
        return startTagStyleScript(token);
      case 'input':
        startTagInput(token);
        return null;
      case 'form':
        startTagForm(token);
        return null;
      default:
        startTagOther(token);
        return null;
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'table':
        endTagTable(token);
        return null;
      case 'body':
      case 'caption':
      case 'col':
      case 'colgroup':
      case 'html':
      case 'tbody':
      case 'td':
      case 'tfoot':
      case 'th':
      case 'thead':
      case 'tr':
        endTagIgnore(token);
        return null;
      default:
        endTagOther(token);
        return null;
    }
  }

  // helper methods
  void clearStackToTableContext() {
    // 'clear the stack back to a table context'
    while (tree.openElements.last.localName != 'table' &&
        tree.openElements.last.localName != 'html') {
      //parser.parseError(token.span, "unexpected-implied-end-tag-in-table",
      //  {"name":  tree.openElements.last.name})
      tree.openElements.removeLast();
    }
    // When the current node is <html> it's an innerHTML case
  }

  // processing methods
  @override
  bool processEOF() {
    final last = tree.openElements.last;
    if (last.localName != 'html') {
      parser.parseError(last.sourceSpan, 'eof-in-table');
    } else {
      assert(parser.innerHTMLMode);
    }
    //Stop parsing
    return false;
  }

  @override
  Token? processSpaceCharacters(SpaceCharactersToken token) {
    final originalPhase = parser.phase;
    parser.phase = parser._inTableTextPhase;
    parser._inTableTextPhase.originalPhase = originalPhase;
    parser.phase.processSpaceCharacters(token);
    return null;
  }

  @override
  Token? processCharacters(CharactersToken token) {
    final originalPhase = parser.phase;
    parser.phase = parser._inTableTextPhase;
    parser._inTableTextPhase.originalPhase = originalPhase;
    parser.phase.processCharacters(token);
    return null;
  }

  void insertText(CharactersToken token) {
    // If we get here there must be at least one non-whitespace character
    // Do the table magic!
    tree.insertFromTable = true;
    parser._inBodyPhase.processCharacters(token);
    tree.insertFromTable = false;
  }

  void startTagCaption(StartTagToken token) {
    clearStackToTableContext();
    tree.activeFormattingElements.add(null);
    tree.insertElement(token);
    parser.phase = parser._inCaptionPhase;
  }

  void startTagColgroup(StartTagToken token) {
    clearStackToTableContext();
    tree.insertElement(token);
    parser.phase = parser._inColumnGroupPhase;
  }

  Token startTagCol(StartTagToken token) {
    startTagColgroup(
        StartTagToken('colgroup', data: LinkedHashMap<Object, String>()));
    return token;
  }

  void startTagRowGroup(StartTagToken token) {
    clearStackToTableContext();
    tree.insertElement(token);
    parser.phase = parser._inTableBodyPhase;
  }

  Token startTagImplyTbody(StartTagToken token) {
    startTagRowGroup(
        StartTagToken('tbody', data: LinkedHashMap<Object, String>()));
    return token;
  }

  Token? startTagTable(StartTagToken token) {
    parser.parseError(token.span, 'unexpected-start-tag-implies-end-tag',
        {'startName': 'table', 'endName': 'table'});
    parser.phase.processEndTag(EndTagToken('table'));
    if (!parser.innerHTMLMode) {
      return token;
    }
    return null;
  }

  Token? startTagStyleScript(StartTagToken token) {
    return parser._inHeadPhase.processStartTag(token);
  }

  void startTagInput(StartTagToken token) {
    if (token.data['type']?.toAsciiLowerCase() == 'hidden') {
      parser.parseError(token.span, 'unexpected-hidden-input-in-table');
      tree.insertElement(token);
      // XXX associate with form
      tree.openElements.removeLast();
    } else {
      startTagOther(token);
    }
  }

  void startTagForm(StartTagToken token) {
    parser.parseError(token.span, 'unexpected-form-in-table');
    if (tree.formPointer == null) {
      tree.insertElement(token);
      tree.formPointer = tree.openElements.last;
      tree.openElements.removeLast();
    }
  }

  void startTagOther(StartTagToken token) {
    parser.parseError(token.span, 'unexpected-start-tag-implies-table-voodoo',
        {'name': token.name});
    // Do the table magic!
    tree.insertFromTable = true;
    parser._inBodyPhase.processStartTag(token);
    tree.insertFromTable = false;
  }

  void endTagTable(EndTagToken token) {
    if (tree.elementInScope('table', variant: 'table')) {
      tree.generateImpliedEndTags();
      final last = tree.openElements.last;
      if (last.localName != 'table') {
        parser.parseError(token.span, 'end-tag-too-early-named',
            {'gotName': 'table', 'expectedName': last.localName});
      }
      while (tree.openElements.last.localName != 'table') {
        tree.openElements.removeLast();
      }
      final node = tree.openElements.removeLast();
      node.endSourceSpan = token.span;
      parser.resetInsertionMode();
    } else {
      // innerHTML case
      assert(parser.innerHTMLMode);
      parser.parseError(token.span, 'undefined-error');
    }
  }

  void endTagIgnore(EndTagToken token) {
    parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name});
  }

  void endTagOther(EndTagToken token) {
    parser.parseError(token.span, 'unexpected-end-tag-implies-table-voodoo',
        {'name': token.name});
    // Do the table magic!
    tree.insertFromTable = true;
    parser._inBodyPhase.processEndTag(token);
    tree.insertFromTable = false;
  }
}

class InTableTextPhase extends Phase {
  Phase? originalPhase;
  List<StringToken> characterTokens;

  InTableTextPhase(super.parser) : characterTokens = <StringToken>[];

  void flushCharacters() {
    if (characterTokens.isEmpty) return;

    // TODO(sigmund,jmesserly): remove '' (dartbug.com/8480)
    final data = characterTokens.map((t) => t.data).join('');
    FileSpan? span;

    if (parser.generateSpans) {
      span = characterTokens[0].span!.expand(characterTokens.last.span!);
    }

    if (!allWhitespace(data)) {
      parser._inTablePhase.insertText(CharactersToken(data)..span = span);
    } else if (data.isNotEmpty) {
      tree.insertText(data, span);
    }
    characterTokens = <StringToken>[];
  }

  @override
  Token processComment(CommentToken token) {
    flushCharacters();
    parser.phase = originalPhase!;
    return token;
  }

  @override
  bool processEOF() {
    flushCharacters();
    parser.phase = originalPhase!;
    return true;
  }

  @override
  Token? processCharacters(CharactersToken token) {
    if (token.data == '\u0000') {
      return null;
    }
    characterTokens.add(token);
    return null;
  }

  @override
  Token? processSpaceCharacters(SpaceCharactersToken token) {
    //pretty sure we should never reach here
    characterTokens.add(token);
    // XXX assert(false);
    return null;
  }

  @override
  Token processStartTag(StartTagToken token) {
    flushCharacters();
    parser.phase = originalPhase!;
    return token;
  }

  @override
  Token processEndTag(EndTagToken token) {
    flushCharacters();
    parser.phase = originalPhase!;
    return token;
  }
}

class InCaptionPhase extends Phase {
  // http://www.whatwg.org/specs/web-apps/current-work///in-caption
  InCaptionPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'caption':
      case 'col':
      case 'colgroup':
      case 'tbody':
      case 'td':
      case 'tfoot':
      case 'th':
      case 'thead':
      case 'tr':
        return startTagTableElement(token);
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'caption':
        endTagCaption(token);
        return null;
      case 'table':
        return endTagTable(token);
      case 'body':
      case 'col':
      case 'colgroup':
      case 'html':
      case 'tbody':
      case 'td':
      case 'tfoot':
      case 'th':
      case 'thead':
      case 'tr':
        endTagIgnore(token);
        return null;
      default:
        return endTagOther(token);
    }
  }

  bool ignoreEndTagCaption() {
    return !tree.elementInScope('caption', variant: 'table');
  }

  @override
  bool processEOF() {
    parser._inBodyPhase.processEOF();
    return false;
  }

  @override
  Token? processCharacters(CharactersToken token) {
    return parser._inBodyPhase.processCharacters(token);
  }

  Token? startTagTableElement(StartTagToken token) {
    parser.parseError(token.span, 'undefined-error');
    //XXX Have to duplicate logic here to find out if the tag is ignored
    final ignoreEndTag = ignoreEndTagCaption();
    parser.phase.processEndTag(EndTagToken('caption'));
    if (!ignoreEndTag) {
      return token;
    }
    return null;
  }

  Token? startTagOther(StartTagToken token) {
    return parser._inBodyPhase.processStartTag(token);
  }

  void endTagCaption(EndTagToken token) {
    if (!ignoreEndTagCaption()) {
      // AT this code is quite similar to endTagTable in "InTable"
      tree.generateImpliedEndTags();
      if (tree.openElements.last.localName != 'caption') {
        parser.parseError(token.span, 'expected-one-end-tag-but-got-another', {
          'gotName': 'caption',
          'expectedName': tree.openElements.last.localName
        });
      }
      while (tree.openElements.last.localName != 'caption') {
        tree.openElements.removeLast();
      }
      final node = tree.openElements.removeLast();
      node.endSourceSpan = token.span;
      tree.clearActiveFormattingElements();
      parser.phase = parser._inTablePhase;
    } else {
      // innerHTML case
      assert(parser.innerHTMLMode);
      parser.parseError(token.span, 'undefined-error');
    }
  }

  Token? endTagTable(EndTagToken token) {
    parser.parseError(token.span, 'undefined-error');
    final ignoreEndTag = ignoreEndTagCaption();
    parser.phase.processEndTag(EndTagToken('caption'));
    if (!ignoreEndTag) {
      return token;
    }
    return null;
  }

  void endTagIgnore(EndTagToken token) {
    parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name});
  }

  Token? endTagOther(EndTagToken token) {
    return parser._inBodyPhase.processEndTag(token);
  }
}

class InColumnGroupPhase extends Phase {
  // http://www.whatwg.org/specs/web-apps/current-work///in-column
  InColumnGroupPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'col':
        startTagCol(token);
        return null;
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'colgroup':
        endTagColgroup(token);
        return null;
      case 'col':
        endTagCol(token);
        return null;
      default:
        return endTagOther(token);
    }
  }

  bool ignoreEndTagColgroup() {
    return tree.openElements.last.localName == 'html';
  }

  @override
  bool processEOF() {
    final ignoreEndTag = ignoreEndTagColgroup();
    if (ignoreEndTag) {
      assert(parser.innerHTMLMode);
      return false;
    } else {
      endTagColgroup(EndTagToken('colgroup'));
      return true;
    }
  }

  @override
  Token? processCharacters(CharactersToken token) {
    final ignoreEndTag = ignoreEndTagColgroup();
    endTagColgroup(EndTagToken('colgroup'));
    return ignoreEndTag ? null : token;
  }

  void startTagCol(StartTagToken token) {
    tree.insertElement(token);
    tree.openElements.removeLast();
  }

  Token? startTagOther(StartTagToken token) {
    final ignoreEndTag = ignoreEndTagColgroup();
    endTagColgroup(EndTagToken('colgroup'));
    return ignoreEndTag ? null : token;
  }

  void endTagColgroup(EndTagToken token) {
    if (ignoreEndTagColgroup()) {
      // innerHTML case
      assert(parser.innerHTMLMode);
      parser.parseError(token.span, 'undefined-error');
    } else {
      final node = tree.openElements.removeLast();
      node.endSourceSpan = token.span;
      parser.phase = parser._inTablePhase;
    }
  }

  void endTagCol(EndTagToken token) {
    parser.parseError(token.span, 'no-end-tag', {'name': 'col'});
  }

  Token? endTagOther(EndTagToken token) {
    final ignoreEndTag = ignoreEndTagColgroup();
    endTagColgroup(EndTagToken('colgroup'));
    return ignoreEndTag ? null : token;
  }
}

class InTableBodyPhase extends Phase {
  // http://www.whatwg.org/specs/web-apps/current-work///in-table0
  InTableBodyPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'tr':
        startTagTr(token);
        return null;
      case 'td':
      case 'th':
        return startTagTableCell(token);
      case 'caption':
      case 'col':
      case 'colgroup':
      case 'tbody':
      case 'tfoot':
      case 'thead':
        return startTagTableOther(token);
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'tbody':
      case 'tfoot':
      case 'thead':
        endTagTableRowGroup(token);
        return null;
      case 'table':
        return endTagTable(token);
      case 'body':
      case 'caption':
      case 'col':
      case 'colgroup':
      case 'html':
      case 'td':
      case 'th':
      case 'tr':
        endTagIgnore(token);
        return null;
      default:
        return endTagOther(token);
    }
  }

  // helper methods
  void clearStackToTableBodyContext() {
    final tableTags = const ['tbody', 'tfoot', 'thead', 'html'];
    while (!tableTags.contains(tree.openElements.last.localName)) {
      //XXX parser.parseError(token.span, "unexpected-implied-end-tag-in-table",
      //  {"name": tree.openElements.last.name})
      tree.openElements.removeLast();
    }
    if (tree.openElements.last.localName == 'html') {
      assert(parser.innerHTMLMode);
    }
  }

  // the rest
  @override
  bool processEOF() {
    parser._inTablePhase.processEOF();
    return false;
  }

  @override
  Token? processSpaceCharacters(SpaceCharactersToken token) {
    return parser._inTablePhase.processSpaceCharacters(token);
  }

  @override
  Token? processCharacters(CharactersToken token) {
    return parser._inTablePhase.processCharacters(token);
  }

  void startTagTr(StartTagToken token) {
    clearStackToTableBodyContext();
    tree.insertElement(token);
    parser.phase = parser._inRowPhase;
  }

  Token startTagTableCell(StartTagToken token) {
    parser.parseError(
        token.span, 'unexpected-cell-in-table-body', {'name': token.name});
    startTagTr(StartTagToken('tr', data: LinkedHashMap<Object, String>()));
    return token;
  }

  Token? startTagTableOther(TagToken token) => endTagTable(token);

  Token? startTagOther(StartTagToken token) {
    return parser._inTablePhase.processStartTag(token);
  }

  void endTagTableRowGroup(EndTagToken token) {
    if (tree.elementInScope(token.name, variant: 'table')) {
      clearStackToTableBodyContext();
      final node = tree.openElements.removeLast();
      node.endSourceSpan = token.span;
      parser.phase = parser._inTablePhase;
    } else {
      parser.parseError(
          token.span, 'unexpected-end-tag-in-table-body', {'name': token.name});
    }
  }

  Token? endTagTable(TagToken token) {
    // XXX AT Any ideas on how to share this with endTagTable?
    if (tree.elementInScope('tbody', variant: 'table') ||
        tree.elementInScope('thead', variant: 'table') ||
        tree.elementInScope('tfoot', variant: 'table')) {
      clearStackToTableBodyContext();
      endTagTableRowGroup(EndTagToken(tree.openElements.last.localName));
      return token;
    } else {
      // innerHTML case
      assert(parser.innerHTMLMode);
      parser.parseError(token.span, 'undefined-error');
    }
    return null;
  }

  void endTagIgnore(EndTagToken token) {
    parser.parseError(
        token.span, 'unexpected-end-tag-in-table-body', {'name': token.name});
  }

  Token? endTagOther(EndTagToken token) {
    return parser._inTablePhase.processEndTag(token);
  }
}

class InRowPhase extends Phase {
  // http://www.whatwg.org/specs/web-apps/current-work///in-row
  InRowPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'td':
      case 'th':
        startTagTableCell(token);
        return null;
      case 'caption':
      case 'col':
      case 'colgroup':
      case 'tbody':
      case 'tfoot':
      case 'thead':
      case 'tr':
        return startTagTableOther(token);
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'tr':
        endTagTr(token);
        return null;
      case 'table':
        return endTagTable(token);
      case 'tbody':
      case 'tfoot':
      case 'thead':
        return endTagTableRowGroup(token);
      case 'body':
      case 'caption':
      case 'col':
      case 'colgroup':
      case 'html':
      case 'td':
      case 'th':
        endTagIgnore(token);
        return null;
      default:
        return endTagOther(token);
    }
  }

  // helper methods (XXX unify this with other table helper methods)
  void clearStackToTableRowContext() {
    while (true) {
      final last = tree.openElements.last;
      if (last.localName == 'tr' || last.localName == 'html') break;

      parser.parseError(
          last.sourceSpan,
          'unexpected-implied-end-tag-in-table-row',
          {'name': tree.openElements.last.localName});
      tree.openElements.removeLast();
    }
  }

  bool ignoreEndTagTr() {
    return !tree.elementInScope('tr', variant: 'table');
  }

  // the rest
  @override
  bool processEOF() {
    parser._inTablePhase.processEOF();
    return false;
  }

  @override
  Token? processSpaceCharacters(SpaceCharactersToken token) {
    return parser._inTablePhase.processSpaceCharacters(token);
  }

  @override
  Token? processCharacters(CharactersToken token) {
    return parser._inTablePhase.processCharacters(token);
  }

  void startTagTableCell(StartTagToken token) {
    clearStackToTableRowContext();
    tree.insertElement(token);
    parser.phase = parser._inCellPhase;
    tree.activeFormattingElements.add(null);
  }

  Token? startTagTableOther(StartTagToken token) {
    final ignoreEndTag = ignoreEndTagTr();
    endTagTr(EndTagToken('tr'));
    // XXX how are we sure it's always ignored in the innerHTML case?
    return ignoreEndTag ? null : token;
  }

  Token? startTagOther(StartTagToken token) {
    return parser._inTablePhase.processStartTag(token);
  }

  void endTagTr(EndTagToken token) {
    if (!ignoreEndTagTr()) {
      clearStackToTableRowContext();
      final node = tree.openElements.removeLast();
      node.endSourceSpan = token.span;
      parser.phase = parser._inTableBodyPhase;
    } else {
      // innerHTML case
      assert(parser.innerHTMLMode);
      parser.parseError(token.span, 'undefined-error');
    }
  }

  Token? endTagTable(EndTagToken token) {
    final ignoreEndTag = ignoreEndTagTr();
    endTagTr(EndTagToken('tr'));
    // Reprocess the current tag if the tr end tag was not ignored
    // XXX how are we sure it's always ignored in the innerHTML case?
    return ignoreEndTag ? null : token;
  }

  Token? endTagTableRowGroup(EndTagToken token) {
    if (tree.elementInScope(token.name, variant: 'table')) {
      endTagTr(EndTagToken('tr'));
      return token;
    } else {
      parser.parseError(token.span, 'undefined-error');
      return null;
    }
  }

  void endTagIgnore(EndTagToken token) {
    parser.parseError(
        token.span, 'unexpected-end-tag-in-table-row', {'name': token.name});
  }

  Token? endTagOther(EndTagToken token) {
    return parser._inTablePhase.processEndTag(token);
  }
}

class InCellPhase extends Phase {
  // http://www.whatwg.org/specs/web-apps/current-work///in-cell
  InCellPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'caption':
      case 'col':
      case 'colgroup':
      case 'tbody':
      case 'td':
      case 'tfoot':
      case 'th':
      case 'thead':
      case 'tr':
        return startTagTableOther(token);
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'td':
      case 'th':
        endTagTableCell(token);
        return null;
      case 'body':
      case 'caption':
      case 'col':
      case 'colgroup':
      case 'html':
        endTagIgnore(token);
        return null;
      case 'table':
      case 'tbody':
      case 'tfoot':
      case 'thead':
      case 'tr':
        return endTagImply(token);
      default:
        return endTagOther(token);
    }
  }

  // helper
  void closeCell() {
    if (tree.elementInScope('td', variant: 'table')) {
      endTagTableCell(EndTagToken('td'));
    } else if (tree.elementInScope('th', variant: 'table')) {
      endTagTableCell(EndTagToken('th'));
    }
  }

  // the rest
  @override
  bool processEOF() {
    parser._inBodyPhase.processEOF();
    return false;
  }

  @override
  Token? processCharacters(CharactersToken token) {
    return parser._inBodyPhase.processCharacters(token);
  }

  Token? startTagTableOther(StartTagToken token) {
    if (tree.elementInScope('td', variant: 'table') ||
        tree.elementInScope('th', variant: 'table')) {
      closeCell();
      return token;
    } else {
      // innerHTML case
      assert(parser.innerHTMLMode);
      parser.parseError(token.span, 'undefined-error');
      return null;
    }
  }

  Token? startTagOther(StartTagToken token) {
    return parser._inBodyPhase.processStartTag(token);
  }

  void endTagTableCell(EndTagToken token) {
    if (tree.elementInScope(token.name, variant: 'table')) {
      tree.generateImpliedEndTags(token.name);
      if (tree.openElements.last.localName != token.name) {
        parser.parseError(
            token.span, 'unexpected-cell-end-tag', {'name': token.name});
        popOpenElementsUntil(token);
      } else {
        final node = tree.openElements.removeLast();
        node.endSourceSpan = token.span;
      }
      tree.clearActiveFormattingElements();
      parser.phase = parser._inRowPhase;
    } else {
      parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name});
    }
  }

  void endTagIgnore(EndTagToken token) {
    parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name});
  }

  Token? endTagImply(EndTagToken token) {
    if (tree.elementInScope(token.name, variant: 'table')) {
      closeCell();
      return token;
    } else {
      // sometimes innerHTML case
      parser.parseError(token.span, 'undefined-error');
    }
    return null;
  }

  Token? endTagOther(EndTagToken token) {
    return parser._inBodyPhase.processEndTag(token);
  }
}

class InSelectPhase extends Phase {
  InSelectPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'option':
        startTagOption(token);
        return null;
      case 'optgroup':
        startTagOptgroup(token);
        return null;
      case 'select':
        startTagSelect(token);
        return null;
      case 'input':
      case 'keygen':
      case 'textarea':
        return startTagInput(token);
      case 'script':
        return startTagScript(token);
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'option':
        endTagOption(token);
        return null;
      case 'optgroup':
        endTagOptgroup(token);
        return null;
      case 'select':
        endTagSelect(token);
        return null;
      default:
        endTagOther(token);
        return null;
    }
  }

  // http://www.whatwg.org/specs/web-apps/current-work///in-select
  @override
  bool processEOF() {
    final last = tree.openElements.last;
    if (last.localName != 'html') {
      parser.parseError(last.sourceSpan, 'eof-in-select');
    } else {
      assert(parser.innerHTMLMode);
    }
    return false;
  }

  @override
  Token? processCharacters(CharactersToken token) {
    if (token.data == '\u0000') {
      return null;
    }
    tree.insertText(token.data, token.span);
    return null;
  }

  void startTagOption(StartTagToken token) {
    // We need to imply </option> if <option> is the current node.
    if (tree.openElements.last.localName == 'option') {
      tree.openElements.removeLast();
    }
    tree.insertElement(token);
  }

  void startTagOptgroup(StartTagToken token) {
    if (tree.openElements.last.localName == 'option') {
      tree.openElements.removeLast();
    }
    if (tree.openElements.last.localName == 'optgroup') {
      tree.openElements.removeLast();
    }
    tree.insertElement(token);
  }

  void startTagSelect(StartTagToken token) {
    parser.parseError(token.span, 'unexpected-select-in-select');
    endTagSelect(EndTagToken('select'));
  }

  Token? startTagInput(StartTagToken token) {
    parser.parseError(token.span, 'unexpected-input-in-select');
    if (tree.elementInScope('select', variant: 'select')) {
      endTagSelect(EndTagToken('select'));
      return token;
    } else {
      assert(parser.innerHTMLMode);
    }
    return null;
  }

  Token? startTagScript(StartTagToken token) {
    return parser._inHeadPhase.processStartTag(token);
  }

  Token? startTagOther(StartTagToken token) {
    parser.parseError(
        token.span, 'unexpected-start-tag-in-select', {'name': token.name});
    return null;
  }

  void endTagOption(EndTagToken token) {
    if (tree.openElements.last.localName == 'option') {
      final node = tree.openElements.removeLast();
      node.endSourceSpan = token.span;
    } else {
      parser.parseError(
          token.span, 'unexpected-end-tag-in-select', {'name': 'option'});
    }
  }

  void endTagOptgroup(EndTagToken token) {
    // </optgroup> implicitly closes <option>
    if (tree.openElements.last.localName == 'option' &&
        tree.openElements[tree.openElements.length - 2].localName ==
            'optgroup') {
      tree.openElements.removeLast();
    }
    // It also closes </optgroup>
    if (tree.openElements.last.localName == 'optgroup') {
      final node = tree.openElements.removeLast();
      node.endSourceSpan = token.span;
      // But nothing else
    } else {
      parser.parseError(
          token.span, 'unexpected-end-tag-in-select', {'name': 'optgroup'});
    }
  }

  void endTagSelect(EndTagToken token) {
    if (tree.elementInScope('select', variant: 'select')) {
      popOpenElementsUntil(token);
      parser.resetInsertionMode();
    } else {
      // innerHTML case
      assert(parser.innerHTMLMode);
      parser.parseError(token.span, 'undefined-error');
    }
  }

  void endTagOther(EndTagToken token) {
    parser.parseError(
        token.span, 'unexpected-end-tag-in-select', {'name': token.name});
  }
}

class InSelectInTablePhase extends Phase {
  InSelectInTablePhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'caption':
      case 'table':
      case 'tbody':
      case 'tfoot':
      case 'thead':
      case 'tr':
      case 'td':
      case 'th':
        return startTagTable(token);
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'caption':
      case 'table':
      case 'tbody':
      case 'tfoot':
      case 'thead':
      case 'tr':
      case 'td':
      case 'th':
        return endTagTable(token);
      default:
        return endTagOther(token);
    }
  }

  @override
  bool processEOF() {
    parser._inSelectPhase.processEOF();
    return false;
  }

  @override
  Token? processCharacters(CharactersToken token) {
    return parser._inSelectPhase.processCharacters(token);
  }

  Token startTagTable(StartTagToken token) {
    parser.parseError(
        token.span,
        'unexpected-table-element-start-tag-in-select-in-table',
        {'name': token.name});
    endTagOther(EndTagToken('select'));
    return token;
  }

  Token? startTagOther(StartTagToken token) {
    return parser._inSelectPhase.processStartTag(token);
  }

  Token? endTagTable(EndTagToken token) {
    parser.parseError(
        token.span,
        'unexpected-table-element-end-tag-in-select-in-table',
        {'name': token.name});
    if (tree.elementInScope(token.name, variant: 'table')) {
      endTagOther(EndTagToken('select'));
      return token;
    }
    return null;
  }

  Token? endTagOther(EndTagToken token) {
    return parser._inSelectPhase.processEndTag(token);
  }
}

class InForeignContentPhase extends Phase {
  // TODO(jmesserly): this is sorted so we could binary search.
  static const breakoutElements = [
    'b',
    'big',
    'blockquote',
    'body',
    'br',
    'center',
    'code',
    'dd',
    'div',
    'dl',
    'dt',
    'em',
    'embed',
    'h1',
    'h2',
    'h3',
    'h4',
    'h5',
    'h6',
    'head',
    'hr',
    'i',
    'img',
    'li',
    'listing',
    'menu',
    'meta',
    'nobr',
    'ol',
    'p',
    'pre',
    'ruby',
    's',
    'small',
    'span',
    'strike',
    'strong',
    'sub',
    'sup',
    'table',
    'tt',
    'u',
    'ul',
    'var'
  ];

  InForeignContentPhase(super.parser);

  void adjustSVGTagNames(StartTagToken token) {
    final replacements = const {
      'altglyph': 'altGlyph',
      'altglyphdef': 'altGlyphDef',
      'altglyphitem': 'altGlyphItem',
      'animatecolor': 'animateColor',
      'animatemotion': 'animateMotion',
      'animatetransform': 'animateTransform',
      'clippath': 'clipPath',
      'feblend': 'feBlend',
      'fecolormatrix': 'feColorMatrix',
      'fecomponenttransfer': 'feComponentTransfer',
      'fecomposite': 'feComposite',
      'feconvolvematrix': 'feConvolveMatrix',
      'fediffuselighting': 'feDiffuseLighting',
      'fedisplacementmap': 'feDisplacementMap',
      'fedistantlight': 'feDistantLight',
      'feflood': 'feFlood',
      'fefunca': 'feFuncA',
      'fefuncb': 'feFuncB',
      'fefuncg': 'feFuncG',
      'fefuncr': 'feFuncR',
      'fegaussianblur': 'feGaussianBlur',
      'feimage': 'feImage',
      'femerge': 'feMerge',
      'femergenode': 'feMergeNode',
      'femorphology': 'feMorphology',
      'feoffset': 'feOffset',
      'fepointlight': 'fePointLight',
      'fespecularlighting': 'feSpecularLighting',
      'fespotlight': 'feSpotLight',
      'fetile': 'feTile',
      'feturbulence': 'feTurbulence',
      'foreignobject': 'foreignObject',
      'glyphref': 'glyphRef',
      'lineargradient': 'linearGradient',
      'radialgradient': 'radialGradient',
      'textpath': 'textPath'
    };

    final replace = replacements[token.name];
    if (replace != null) {
      token.name = replace;
    }
  }

  @override
  Token? processCharacters(CharactersToken token) {
    if (token.data == '\u0000') {
      token.replaceData('\uFFFD');
    } else if (parser.framesetOK && !allWhitespace(token.data)) {
      parser.framesetOK = false;
    }
    return super.processCharacters(token);
  }

  @override
  Token? processStartTag(StartTagToken token) {
    final currentNode = tree.openElements.last;
    if (breakoutElements.contains(token.name) ||
        (token.name == 'font' &&
            (token.data.containsKey('color') ||
                token.data.containsKey('face') ||
                token.data.containsKey('size')))) {
      parser.parseError(token.span,
          'unexpected-html-element-in-foreign-content', {'name': token.name});
      while (tree.openElements.last.namespaceUri != tree.defaultNamespace &&
          !parser.isHTMLIntegrationPoint(tree.openElements.last) &&
          !parser.isMathMLTextIntegrationPoint(tree.openElements.last)) {
        tree.openElements.removeLast();
      }
      return token;
    } else {
      if (currentNode.namespaceUri == Namespaces.mathml) {
        parser.adjustMathMLAttributes(token);
      } else if (currentNode.namespaceUri == Namespaces.svg) {
        adjustSVGTagNames(token);
        parser.adjustSVGAttributes(token);
      }
      parser.adjustForeignAttributes(token);
      token.namespace = currentNode.namespaceUri;
      tree.insertElement(token);
      if (token.selfClosing) {
        tree.openElements.removeLast();
        token.selfClosingAcknowledged = true;
      }
      return null;
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    var nodeIndex = tree.openElements.length - 1;
    var node = tree.openElements.last;
    if (node.localName?.toAsciiLowerCase() != token.name) {
      parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name});
    }

    Token? newToken;
    while (true) {
      if (node.localName?.toAsciiLowerCase() == token.name) {
        //XXX this isn't in the spec but it seems necessary
        if (parser.phase == parser._inTableTextPhase) {
          final inTableText = parser.phase as InTableTextPhase;
          inTableText.flushCharacters();
          parser.phase = inTableText.originalPhase!;
        }
        while (tree.openElements.removeLast() != node) {
          assert(tree.openElements.isNotEmpty);
        }
        newToken = null;
        break;
      }
      nodeIndex -= 1;

      node = tree.openElements[nodeIndex];
      if (node.namespaceUri != tree.defaultNamespace) {
        continue;
      } else {
        newToken = parser.phase.processEndTag(token);
        break;
      }
    }
    return newToken;
  }
}

class AfterBodyPhase extends Phase {
  AfterBodyPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    if (token.name == 'html') return startTagHtml(token);
    return startTagOther(token);
  }

  @override
  Token? processEndTag(EndTagToken token) {
    if (token.name == 'html') {
      endTagHtml(token);
      return null;
    }
    return endTagOther(token);
  }

  //Stop parsing
  @override
  bool processEOF() => false;

  @override
  Token? processComment(CommentToken token) {
    // This is needed because data is to be appended to the <html> element
    // here and not to whatever is currently open.
    tree.insertComment(token, tree.openElements[0]);
    return null;
  }

  @override
  Token processCharacters(CharactersToken token) {
    parser.parseError(token.span, 'unexpected-char-after-body');
    parser.phase = parser._inBodyPhase;
    return token;
  }

  @override
  Token? startTagHtml(StartTagToken token) {
    return parser._inBodyPhase.processStartTag(token);
  }

  Token startTagOther(StartTagToken token) {
    parser.parseError(
        token.span, 'unexpected-start-tag-after-body', {'name': token.name});
    parser.phase = parser._inBodyPhase;
    return token;
  }

  void endTagHtml(Token token) {
    for (var node in tree.openElements.reversed) {
      if (node.localName == 'html') {
        node.endSourceSpan = token.span;
        break;
      }
    }
    if (parser.innerHTMLMode) {
      parser.parseError(token.span, 'unexpected-end-tag-after-body-innerhtml');
    } else {
      parser.phase = parser._afterAfterBodyPhase;
    }
  }

  Token endTagOther(EndTagToken token) {
    parser.parseError(
        token.span, 'unexpected-end-tag-after-body', {'name': token.name});
    parser.phase = parser._inBodyPhase;
    return token;
  }
}

class InFramesetPhase extends Phase {
  // http://www.whatwg.org/specs/web-apps/current-work///in-frameset
  InFramesetPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'frameset':
        startTagFrameset(token);
        return null;
      case 'frame':
        startTagFrame(token);
        return null;
      case 'noframes':
        return startTagNoframes(token);
      default:
        return startTagOther(token);
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'frameset':
        endTagFrameset(token);
        return null;
      default:
        endTagOther(token);
        return null;
    }
  }

  @override
  bool processEOF() {
    final last = tree.openElements.last;
    if (last.localName != 'html') {
      parser.parseError(last.sourceSpan, 'eof-in-frameset');
    } else {
      assert(parser.innerHTMLMode);
    }
    return false;
  }

  @override
  Token? processCharacters(CharactersToken token) {
    parser.parseError(token.span, 'unexpected-char-in-frameset');
    return null;
  }

  void startTagFrameset(StartTagToken token) {
    tree.insertElement(token);
  }

  void startTagFrame(StartTagToken token) {
    tree.insertElement(token);
    tree.openElements.removeLast();
  }

  Token? startTagNoframes(StartTagToken token) {
    return parser._inBodyPhase.processStartTag(token);
  }

  Token? startTagOther(StartTagToken token) {
    parser.parseError(
        token.span, 'unexpected-start-tag-in-frameset', {'name': token.name});
    return null;
  }

  void endTagFrameset(EndTagToken token) {
    if (tree.openElements.last.localName == 'html') {
      // innerHTML case
      parser.parseError(
          token.span, 'unexpected-frameset-in-frameset-innerhtml');
    } else {
      final node = tree.openElements.removeLast();
      node.endSourceSpan = token.span;
    }
    if (!parser.innerHTMLMode &&
        tree.openElements.last.localName != 'frameset') {
      // If we're not in innerHTML mode and the the current node is not a
      // "frameset" element (anymore) then switch.
      parser.phase = parser._afterFramesetPhase;
    }
  }

  void endTagOther(EndTagToken token) {
    parser.parseError(
        token.span, 'unexpected-end-tag-in-frameset', {'name': token.name});
  }
}

class AfterFramesetPhase extends Phase {
  // http://www.whatwg.org/specs/web-apps/current-work///after3
  AfterFramesetPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'noframes':
        return startTagNoframes(token);
      default:
        startTagOther(token);
        return null;
    }
  }

  @override
  Token? processEndTag(EndTagToken token) {
    switch (token.name) {
      case 'html':
        endTagHtml(token);
        return null;
      default:
        endTagOther(token);
        return null;
    }
  }

  // Stop parsing
  @override
  bool processEOF() => false;

  @override
  Token? processCharacters(CharactersToken token) {
    parser.parseError(token.span, 'unexpected-char-after-frameset');
    return null;
  }

  Token? startTagNoframes(StartTagToken token) {
    return parser._inHeadPhase.processStartTag(token);
  }

  void startTagOther(StartTagToken token) {
    parser.parseError(token.span, 'unexpected-start-tag-after-frameset',
        {'name': token.name});
  }

  void endTagHtml(EndTagToken token) {
    parser.phase = parser._afterAfterFramesetPhase;
  }

  void endTagOther(EndTagToken token) {
    parser.parseError(
        token.span, 'unexpected-end-tag-after-frameset', {'name': token.name});
  }
}

class AfterAfterBodyPhase extends Phase {
  AfterAfterBodyPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    if (token.name == 'html') return startTagHtml(token);
    return startTagOther(token);
  }

  @override
  bool processEOF() => false;

  @override
  Token? processComment(CommentToken token) {
    tree.insertComment(token, tree.document);
    return null;
  }

  @override
  Token? processSpaceCharacters(SpaceCharactersToken token) {
    return parser._inBodyPhase.processSpaceCharacters(token);
  }

  @override
  Token processCharacters(CharactersToken token) {
    parser.parseError(token.span, 'expected-eof-but-got-char');
    parser.phase = parser._inBodyPhase;
    return token;
  }

  @override
  Token? startTagHtml(StartTagToken token) {
    return parser._inBodyPhase.processStartTag(token);
  }

  Token startTagOther(StartTagToken token) {
    parser.parseError(
        token.span, 'expected-eof-but-got-start-tag', {'name': token.name});
    parser.phase = parser._inBodyPhase;
    return token;
  }

  @override
  Token processEndTag(EndTagToken token) {
    parser.parseError(
        token.span, 'expected-eof-but-got-end-tag', {'name': token.name});
    parser.phase = parser._inBodyPhase;
    return token;
  }
}

class AfterAfterFramesetPhase extends Phase {
  AfterAfterFramesetPhase(super.parser);

  @override
  Token? processStartTag(StartTagToken token) {
    switch (token.name) {
      case 'html':
        return startTagHtml(token);
      case 'noframes':
        return startTagNoFrames(token);
      default:
        startTagOther(token);
        return null;
    }
  }

  @override
  bool processEOF() => false;

  @override
  Token? processComment(CommentToken token) {
    tree.insertComment(token, tree.document);
    return null;
  }

  @override
  Token? processSpaceCharacters(SpaceCharactersToken token) {
    return parser._inBodyPhase.processSpaceCharacters(token);
  }

  @override
  Token? processCharacters(CharactersToken token) {
    parser.parseError(token.span, 'expected-eof-but-got-char');
    return null;
  }

  @override
  Token? startTagHtml(StartTagToken token) {
    return parser._inBodyPhase.processStartTag(token);
  }

  Token? startTagNoFrames(StartTagToken token) {
    return parser._inHeadPhase.processStartTag(token);
  }

  void startTagOther(StartTagToken token) {
    parser.parseError(
        token.span, 'expected-eof-but-got-start-tag', {'name': token.name});
  }

  @override
  Token? processEndTag(EndTagToken token) {
    parser.parseError(
        token.span, 'expected-eof-but-got-end-tag', {'name': token.name});
    return null;
  }
}

/// Error in parsed document.
class ParseError implements SourceSpanException {
  final String errorCode;
  @override
  final SourceSpan? span;
  final Map<String, Object?>? data;

  ParseError(this.errorCode, this.span, this.data);

  int get line => span!.start.line;

  int get column => span!.start.column;

  /// Returns the human readable error message for this error.
  ///
  /// Use [SourceSpan.message] or the [toString] from the [span] field to get a
  /// message including span information
  @override
  String get message => formatStr(errorMessages[errorCode]!, data);

  @override
  String toString({dynamic color}) {
    if (span == null) {
      return message;
    }
    final res = span!.message(message, color: color);
    return span!.sourceUrl == null ? 'ParserError on $res' : 'On $res';
  }
}

/// Convenience function to get the pair of namespace and localName.
(String, String?) getElementNameTuple(Element e) {
  final ns = e.namespaceUri ?? Namespaces.html;
  return (ns, e.localName);
}
