/// Internals to the tree builders.
library;

import 'dart:collection';

import 'package:source_span/source_span.dart';

import '../dom.dart';
import '../parser.dart' show getElementNameTuple;
import 'constants.dart';
import 'list_proxy.dart';
import 'token.dart';

/// Open elements in the formatting category, most recent element last.
///
/// `null` is used as the "marker" entry to prevent style from leaking when
/// entering some elements.
///
/// https://html.spec.whatwg.org/multipage/parsing.html#list-of-active-formatting-elements
class ActiveFormattingElements extends ListProxy<Element?> {
  /// Push an element into the active formatting elements.
  ///
  /// Prevents equivalent elements from appearing more than 3 times following
  /// the last `null` marker. If adding [node] would cause there to be more than
  /// 3 equivalent elements the earliest identical element is removed.
  // TODO - Earliest equivalent following a marker, as opposed to earliest
  // identical regardless of marker position, should be removed.
  @override
  void add(Element? node) {
    var equalCount = 0;
    if (node != null) {
      for (var element in reversed) {
        if (element == null) {
          break;
        }
        if (_nodesEqual(element, node)) {
          equalCount += 1;
        }
        if (equalCount == 3) {
          // TODO - https://github.com/dart-lang/html/issues/135
          remove(element);
          break;
        }
      }
    }
    super.add(node);
  }
}

// TODO(jmesserly): this should exist in corelib...
bool _mapEquals(Map<Object, String> a, Map<Object, String> b) {
  if (a.length != b.length) return false;
  if (a.isEmpty) return true;

  for (var keyA in a.keys) {
    final valB = b[keyA];
    if (valB == null && !b.containsKey(keyA)) {
      return false;
    }

    if (a[keyA] != valB) {
      return false;
    }
  }
  return true;
}

bool _nodesEqual(Element node1, Element node2) {
  return getElementNameTuple(node1) == getElementNameTuple(node2) &&
      _mapEquals(node1.attributes, node2.attributes);
}

/// Basic treebuilder implementation.
class TreeBuilder {
  final String? defaultNamespace;

  late Document document;

  final List<Element> openElements = <Element>[];

  final activeFormattingElements = ActiveFormattingElements();

  Node? headPointer;

  Element? formPointer;

  /// Switch the function used to insert an element from the
  /// normal one to the misnested table one and back again
  bool insertFromTable = false;

  TreeBuilder(bool namespaceHTMLElements)
      : defaultNamespace = namespaceHTMLElements ? Namespaces.html : null {
    reset();
  }

  void reset() {
    openElements.clear();
    activeFormattingElements.clear();

    //XXX - rename these to headElement, formElement
    headPointer = null;
    formPointer = null;

    insertFromTable = false;

    document = Document();
  }

  bool elementInScope(dynamic target, {String? variant}) {
    // If we pass a node in we match that. If we pass a string match any node
    // with that name.
    final exactNode = target is Node;

    var setElements1 = scopingElements;
    var setElements2 = const <(String, String)>{};
    var invert = false;
    if (variant != null) {
      switch (variant) {
        case 'button':
          setElements2 = const {(Namespaces.html, 'button')};
          break;
        case 'list':
          setElements2 = const {
            (Namespaces.html, 'ol'),
            (Namespaces.html, 'ul')
          };
          break;
        case 'table':
          setElements1 = const {
            (Namespaces.html, 'html'),
            (Namespaces.html, 'table')
          };
          break;
        case 'select':
          setElements1 = const {
            (Namespaces.html, 'optgroup'),
            (Namespaces.html, 'option')
          };
          invert = true;
          break;
        default:
          throw StateError('We should never reach this point');
      }
    }

    for (var node in openElements.reversed) {
      if (!exactNode && node.localName == target ||
          exactNode && node == target) {
        return true;
      } else if (invert !=
          (setElements1.contains(getElementNameTuple(node)) ||
              setElements2.contains(getElementNameTuple(node)))) {
        return false;
      }
    }

    throw StateError('We should never reach this point');
  }

  void reconstructActiveFormattingElements() {
    // Within this algorithm the order of steps described in the
    // specification is not quite the same as the order of steps in the
    // code. It should still do the same though.

    // Step 1: stop the algorithm when there's nothing to do.
    if (activeFormattingElements.isEmpty) {
      return;
    }

    // Step 2 and step 3: we start with the last element. So i is -1.
    var i = activeFormattingElements.length - 1;
    var entry = activeFormattingElements[i];
    if (entry == null || openElements.contains(entry)) {
      return;
    }

    // Step 6
    while (entry != null && !openElements.contains(entry)) {
      if (i == 0) {
        //This will be reset to 0 below
        i = -1;
        break;
      }
      i -= 1;
      // Step 5: let entry be one earlier in the list.
      entry = activeFormattingElements[i];
    }

    while (true) {
      // Step 7
      i += 1;

      // Step 8
      entry = activeFormattingElements[i];

      // TODO(jmesserly): optimize this. No need to create a token.
      final cloneToken = StartTagToken(entry!.localName,
          namespace: entry.namespaceUri,
          data: LinkedHashMap.from(entry.attributes))
        ..span = entry.sourceSpan;

      // Step 9
      final element = insertElement(cloneToken);

      // Step 10
      activeFormattingElements[i] = element;

      // Step 11
      if (element == activeFormattingElements.last) {
        break;
      }
    }
  }

  void clearActiveFormattingElements() {
    var entry = activeFormattingElements.removeLast();
    while (activeFormattingElements.isNotEmpty && entry != null) {
      entry = activeFormattingElements.removeLast();
    }
  }

  /// Check if an element exists between the end of the active
  /// formatting elements and the last marker. If it does, return it, else
  /// return null.
  Element? elementInActiveFormattingElements(String? name) {
    for (var item in activeFormattingElements.reversed) {
      // Check for Marker first because if it's a Marker it doesn't have a
      // name attribute.
      if (item == null) {
        break;
      } else if (item.localName == name) {
        return item;
      }
    }
    return null;
  }

  void insertRoot(StartTagToken token) {
    final element = createElement(token);
    openElements.add(element);
    document.nodes.add(element);
  }

  void insertDoctype(DoctypeToken token) {
    final doctype = DocumentType(token.name, token.publicId, token.systemId)
      ..sourceSpan = token.span;
    document.nodes.add(doctype);
  }

  void insertComment(StringToken token, [Node? parent]) {
    parent ??= openElements.last;
    parent.nodes.add(Comment(token.data)..sourceSpan = token.span);
  }

  /// Create an element but don't insert it anywhere
  Element createElement(StartTagToken token) {
    final name = token.name;
    final namespace = token.namespace ?? defaultNamespace;
    final element = document.createElementNS(namespace, name)
      ..attributes = token.data
      ..sourceSpan = token.span;
    return element;
  }

  Element insertElement(StartTagToken token) {
    if (insertFromTable) return insertElementTable(token);
    return insertElementNormal(token);
  }

  Element insertElementNormal(StartTagToken token) {
    final name = token.name;
    final namespace = token.namespace ?? defaultNamespace;
    final element = document.createElementNS(namespace, name)
      ..attributes = token.data
      ..sourceSpan = token.span;
    openElements.last.nodes.add(element);
    openElements.add(element);
    return element;
  }

  Element insertElementTable(StartTagToken token) {
    /// Create an element and insert it into the tree
    final element = createElement(token);
    if (!tableInsertModeElements.contains(openElements.last.localName)) {
      return insertElementNormal(token);
    } else {
      // We should be in the InTable mode. This means we want to do
      // special magic element rearranging
      final nodePos = getTableMisnestedNodePosition();
      if (nodePos[1] == null) {
        // TODO(jmesserly): I don't think this is reachable. If insertFromTable
        // is true, there will be a <table> element open, and it always has a
        // parent pointer.
        nodePos[0]!.nodes.add(element);
      } else {
        nodePos[0]!.insertBefore(element, nodePos[1]);
      }
      openElements.add(element);
    }
    return element;
  }

  /// Insert text data.
  void insertText(String data, FileSpan? span) {
    final parent = openElements.last;

    if (!insertFromTable ||
        insertFromTable &&
            !tableInsertModeElements.contains(openElements.last.localName)) {
      _insertText(parent, data, span);
    } else {
      // We should be in the InTable mode. This means we want to do
      // special magic element rearranging
      final nodePos = getTableMisnestedNodePosition();
      _insertText(nodePos[0]!, data, span, nodePos[1] as Element?);
    }
  }

  /// Insert [data] as text in the current node, positioned before the
  /// start of node [refNode] or to the end of the node's text.
  static void _insertText(Node parent, String data, FileSpan? span,
      [Element? refNode]) {
    final nodes = parent.nodes;
    if (refNode == null) {
      if (nodes.isNotEmpty && nodes.last is Text) {
        final last = nodes.last as Text;
        last.appendData(data);

        if (span != null) {
          last.sourceSpan =
              span.file.span(last.sourceSpan!.start.offset, span.end.offset);
        }
      } else {
        nodes.add(Text(data)..sourceSpan = span);
      }
    } else {
      final index = nodes.indexOf(refNode);
      if (index > 0 && nodes[index - 1] is Text) {
        final last = nodes[index - 1] as Text;
        last.appendData(data);
      } else {
        nodes.insert(index, Text(data)..sourceSpan = span);
      }
    }
  }

  /// Get the foster parent element, and sibling to insert before
  /// (or null) when inserting a misnested table node
  List<Node?> getTableMisnestedNodePosition() {
    // The foster parent element is the one which comes before the most
    // recently opened table element
    // XXX - this is really inelegant
    Element? lastTable;
    Node? fosterParent;
    Node? insertBefore;
    for (var elm in openElements.reversed) {
      if (elm.localName == 'table') {
        lastTable = elm;
        break;
      }
    }
    if (lastTable != null) {
      // XXX - we should really check that this parent is actually a
      // node here
      if (lastTable.parentNode != null) {
        fosterParent = lastTable.parentNode;
        insertBefore = lastTable;
      } else {
        fosterParent = openElements[openElements.indexOf(lastTable) - 1];
      }
    } else {
      fosterParent = openElements[0];
    }
    return [fosterParent, insertBefore];
  }

  void generateImpliedEndTags([String? exclude]) {
    final name = openElements.last.localName;
    // XXX td, th and tr are not actually needed
    if (name != exclude &&
        const ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt']
            .contains(name)) {
      openElements.removeLast();
      // XXX This is not entirely what the specification says. We should
      // investigate it more closely.
      generateImpliedEndTags(exclude);
    }
  }

  /// Return the final tree.
  Document getDocument() => document;

  /// Return the final fragment.
  DocumentFragment getFragment() {
    //XXX assert innerHTML
    final fragment = DocumentFragment();
    openElements[0].reparentChildren(fragment);
    return fragment;
  }
}
