// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// Tools for manipulating HTML during code generation of analyzer and analysis
/// server.
import 'package:html/dom.dart' as dom;

/// Make a deep copy of the given HTML nodes.
List<dom.Node> cloneHtmlNodes(List<dom.Node> nodes) =>
    nodes.map((dom.Node node) => node.clone(true)).toList();

/// Return true if the given iterable contains only whitespace text nodes.
bool containsOnlyWhitespace(Iterable<dom.Node> nodes) {
  for (var node in nodes) {
    if (!isWhitespaceNode(node)) {
      return false;
    }
  }
  return true;
}

/// Get the text contents of the element, ignoring all markup.
String innerText(dom.Element parent) {
  var buffer = StringBuffer();
  void recurse(dom.Element parent) {
    for (var child in parent.nodes) {
      if (child is dom.Text) {
        buffer.write(child.text);
      } else if (child is dom.Element) {
        recurse(child);
      }
    }
  }

  recurse(parent);
  return buffer.toString();
}

/// Return true if the given node is a text node containing only whitespace, or
/// a comment.
bool isWhitespaceNode(dom.Node node) {
  if (node is dom.Element) {
    return false;
  } else if (node is dom.Text) {
    return node.text.trim().isEmpty;
  }
  // Treat all other types of nodes (e.g. comments) as whitespace.
  return true;
}

/// Create an HTML element with the given name, attributes, and child nodes.
dom.Element makeElement(
    String name, Map<Object, String> attributes, List<dom.Node> children) {
  var result = dom.Element.tag(name);
  result.attributes.addAll(attributes);
  for (var child in children) {
    result.append(child);
  }
  return result;
}

/// Mixin class for generating HTML.
mixin HtmlGenerator {
  List<dom.Node> _html = [];

  /// Add the given [node] to the HTML output.
  void add(dom.Node node) {
    _html.add(node);
  }

  /// Add the given [nodes] to the HTML output.
  void addAll(Iterable<dom.Node> nodes) {
    for (var node in nodes) {
      add(node);
    }
  }

  /// Execute [callback], collecting any code that is output using [write],
  /// [writeln], [add], [addAll] or [element], and return the result as a list
  /// of HTML nodes.
  List<dom.Node> collectHtml(void Function()? callback) {
    var oldHtml = _html;
    try {
      _html = <dom.Node>[];
      if (callback != null) {
        callback();
      }
      return _html;
    } finally {
      _html = oldHtml;
    }
  }

  /// Execute [callback], wrapping its output in an element with the given
  /// [name] and [attributes].
  void element(String name, Map<Object, String> attributes,
      [void Function()? callback]) {
    add(makeElement(name, attributes, collectHtml(callback)));
  }

  /// Output text without ending the current line.
  void write(String text) {
    _html.add(dom.Text(text));
  }

  /// Output text, ending the current line.
  void writeln([Object obj = '']) {
    write('$obj\n');
  }
}
