// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:html' as html;

import 'package:meta/meta.dart';
import 'package:ui/ui.dart' as ui;

import '../browser_detection.dart';
import '../dom_renderer.dart';
import '../util.dart';
import 'measurement.dart';
import 'paragraph.dart';

String buildCssFontString({
  required ui.FontStyle? fontStyle,
  required ui.FontWeight? fontWeight,
  required double? fontSize,
  required String fontFamily,
}) {
  final StringBuffer result = StringBuffer();

  // Font style
  if (fontStyle != null) {
    result.write(fontStyle == ui.FontStyle.normal ? 'normal' : 'italic');
  } else {
    result.write(DomRenderer.defaultFontStyle);
  }
  result.write(' ');

  // Font weight.
  if (fontWeight != null) {
    result.write(fontWeightToCss(fontWeight));
  } else {
    result.write(DomRenderer.defaultFontWeight);
  }
  result.write(' ');

  if (fontSize != null) {
    result.write(fontSize.floor());
  } else {
    result.write(DomRenderer.defaultFontSize);
  }
  result.write('px ');
  result.write(canonicalizeFontFamily(fontFamily));

  return result.toString();
}

/// Contains the subset of [ui.ParagraphStyle] properties that affect layout.
class ParagraphGeometricStyle {
  ParagraphGeometricStyle({
    required this.textDirection,
    required this.textAlign,
    this.fontWeight,
    this.fontStyle,
    this.fontFamily,
    this.fontSize,
    this.lineHeight,
    this.maxLines,
    this.letterSpacing,
    this.wordSpacing,
    this.decoration,
    this.ellipsis,
    this.shadows,
  });

  final ui.TextDirection textDirection;
  final ui.TextAlign textAlign;
  final ui.FontWeight? fontWeight;
  final ui.FontStyle? fontStyle;
  final String? fontFamily;
  final double? fontSize;
  final double? lineHeight;
  final int? maxLines;
  final double? letterSpacing;
  final double? wordSpacing;
  final String? decoration;
  final String? ellipsis;
  final List<ui.Shadow>? shadows;

  // Since all fields above are primitives, cache hashcode since ruler lookups
  // use this style as key.
  int? _cachedHashCode;

  /// Returns the font-family that should be used to style the paragraph. It may
  /// or may not be different from [fontFamily]:
  ///
  /// - Always returns "Ahem" in tests.
  /// - Provides correct defaults when [fontFamily] doesn't have a value.
  String get effectiveFontFamily {
    if (assertionsEnabled) {
      // In widget tests we use a predictable-size font "Ahem". This makes
      // widget tests predictable and less flaky.
      if (ui.debugEmulateFlutterTesterEnvironment) {
        return 'Ahem';
      }
    }
    final String? localFontFamily = fontFamily;
    if (localFontFamily == null || localFontFamily.isEmpty) {
      return DomRenderer.defaultFontFamily;
    }
    return localFontFamily;
  }

  String? _cssFontString;

  /// Cached font string that can be used in CSS.
  ///
  /// See <https://developer.mozilla.org/en-US/docs/Web/CSS/font>.
  String get cssFontString {
    return _cssFontString ??= buildCssFontString(
      fontStyle: fontStyle,
      fontWeight: fontWeight,
      fontSize: fontSize,
      fontFamily: effectiveFontFamily,
    );
  }

  TextHeightStyle? _cachedHeightStyle;

  TextHeightStyle get textHeightStyle {
    TextHeightStyle? style = _cachedHeightStyle;
    if (style == null) {
      style = TextHeightStyle(
        fontFamily: effectiveFontFamily,
        fontSize: fontSize ?? DomRenderer.defaultFontSize,
        height: lineHeight,
        // TODO(mdebbar): Pass the actual value when font features become supported
        //                https://github.com/flutter/flutter/issues/64595
        fontFeatures: null,
      );
      _cachedHeightStyle = style;
    }
    return style;
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is ParagraphGeometricStyle
        && other.textDirection == textDirection
        && other.textAlign == textAlign
        && other.fontWeight == fontWeight
        && other.fontStyle == fontStyle
        && other.fontFamily == fontFamily
        && other.fontSize == fontSize
        && other.lineHeight == lineHeight
        && other.maxLines == maxLines
        && other.letterSpacing == letterSpacing
        && other.wordSpacing == wordSpacing
        && other.decoration == decoration
        && other.ellipsis == ellipsis;
  }

  @override
  int get hashCode => _cachedHashCode ??= ui.hashValues(
        textDirection,
        textAlign,
        fontWeight,
        fontStyle,
        fontFamily,
        fontSize,
        lineHeight,
        maxLines,
        letterSpacing,
        wordSpacing,
        decoration,
        ellipsis,
      );

  @override
  String toString() {
    if (assertionsEnabled) {
      return '$runtimeType(textDirection: $textDirection, textAlign: $textAlign,'
          ' fontWeight: $fontWeight,'
          ' fontStyle: $fontStyle,'
          ' fontFamily: $fontFamily, fontSize: $fontSize,'
          ' lineHeight: $lineHeight,'
          ' maxLines: $maxLines,'
          ' letterSpacing: $letterSpacing,'
          ' wordSpacing: $wordSpacing,'
          ' decoration: $decoration,'
          ' ellipsis: $ellipsis,'
          ')';
    } else {
      return super.toString();
    }
  }
}

/// Contains all styles that have an effect on the height of text.
///
/// This is useful as a cache key for [TextHeightRuler]. It's more efficient
/// than using the entire [ParagraphGeometricStyle] as a cache key.
class TextHeightStyle {
  TextHeightStyle({
    required this.fontFamily,
    required this.fontSize,
    required this.height,
    required this.fontFeatures,
  });

  final String fontFamily;
  final double fontSize;
  final double? height;
  final List<ui.FontFeature>? fontFeatures;

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    return other is TextHeightStyle && other.hashCode == hashCode;
  }

  @override
  late final int hashCode = ui.hashValues(
    fontFamily,
    fontSize,
    height,
    ui.hashList(fontFeatures),
  );
}

/// Provides text dimensions found on [_element]. The idea behind this class is
/// to allow the [ParagraphRuler] to mutate multiple dom elements and allow
/// consumers to lazily read the measurements.
///
/// The [ParagraphRuler] would have multiple instances of [TextDimensions] with
/// different backing elements for different types of measurements. When a
/// measurement is needed, the [ParagraphRuler] would mutate all the backing
/// elements at once. The consumer of the ruler can later read those
/// measurements.
///
/// The rationale behind this is to minimize browser reflows by batching dom
/// writes first, then performing all the reads.
class TextDimensions {
  TextDimensions(this._element);

  final html.HtmlElement _element;
  html.Rectangle<num>? _cachedBoundingClientRect;

  /// Attempts to efficiently copy text from [from].
  ///
  /// The primary efficiency gain is from rare occurrence of rich text in
  /// typical apps.
  void updateText(DomParagraph from, ParagraphGeometricStyle style) {
    assert(from != null); // ignore: unnecessary_null_comparison
    assert(_element != null); // ignore: unnecessary_null_comparison
    assert(from.debugHasSameRootStyle(style));
    assert(() {
      final bool wasEmptyOrPlainText = _element.childNodes.isEmpty ||
          (_element.childNodes.length == 1 &&
              _element.childNodes.first is html.Text);
      if (!wasEmptyOrPlainText) {
        throw Exception(
            'Failed to copy text into the paragraph measuring element. The '
            'element already contains rich text "${_element.innerHtml}". It is '
            'likely that a previous measurement did not clean up after '
            'itself.');
      }
      return true;
    }());

    _invalidateBoundsCache();
    final String? plainText = from.plainText;
    if (plainText != null) {
      // Plain text: just set the string. The paragraph's style is assumed to
      // match the style set on the `element`. Setting text as plain string is
      // faster because it doesn't change the DOM structure or CSS attributes,
      // and therefore doesn't trigger style recalculations in the browser.
      if (plainText.endsWith('\n')) {
        // On the web the last newline is ignored. To be consistent with
        // native engine implementation we add extra newline to get correct
        // height measurement.
        _element.text = '$plainText\n';
      } else {
        _element.text = plainText;
      }
    } else {
      // Rich text: deeply copy contents. This is the slow case that should be
      // avoided if fast layout performance is desired.
      final html.Element copy = from.paragraphElement.clone(true) as html.Element;
      _element.nodes.addAll(copy.nodes);
    }
  }

  /// Updated element style width.
  void updateConstraintWidth(double width, String? ellipsis) {
    _invalidateBoundsCache();

    if (width.isInfinite) {
      _element.style
        ..width = null
        ..whiteSpace = 'pre';
    } else if (ellipsis != null) {
      // Width is finite, but we don't want to let the text soft-wrap when
      // ellipsis overflow is enabled.
      _element.style
        ..width = '${width}px'
        ..whiteSpace = 'pre';
    } else {
      // Width is finite and there's no ellipsis overflow.
      _element.style
        ..width = '${width}px'
        ..whiteSpace = 'pre-wrap';
    }
  }

  void _invalidateBoundsCache() {
    _cachedBoundingClientRect = null;
  }

  /// Sets text of contents to a single space character to measure empty text.
  void updateTextToSpace() {
    _invalidateBoundsCache();
    _element.text = ' ';
  }

  /// Applies geometric style properties to the [element].
  void applyStyle(ParagraphGeometricStyle style) {
    final html.CssStyleDeclaration elementStyle = _element.style;
    elementStyle
      ..direction = textDirectionToCss(style.textDirection)
      ..textAlign = textAlignToCssValue(style.textAlign, style.textDirection)
      ..fontSize = style.fontSize != null ? '${style.fontSize!.floor()}px' : null
      ..fontFamily = canonicalizeFontFamily(style.effectiveFontFamily)
      ..fontWeight =
          style.fontWeight != null ? fontWeightToCss(style.fontWeight) : null
      ..fontStyle = style.fontStyle != null
          ? style.fontStyle == ui.FontStyle.normal ? 'normal' : 'italic'
          : null
      ..letterSpacing =
          style.letterSpacing != null ? '${style.letterSpacing}px' : null
      ..wordSpacing =
          style.wordSpacing != null ? '${style.wordSpacing}px' : null;
    final String? decoration = style.decoration;
    if (browserEngine == BrowserEngine.webkit) {
      DomRenderer.setElementStyle(
          _element, '-webkit-text-decoration', decoration);
    } else {
      elementStyle.textDecoration = decoration;
    }
    if (style.lineHeight != null) {
      elementStyle.lineHeight = style.lineHeight!.toString();
    }
    _invalidateBoundsCache();
  }

  void applyHeightStyle(TextHeightStyle textHeightStyle) {
    final String fontFamily = textHeightStyle.fontFamily;
    final double fontSize = textHeightStyle.fontSize;
    final html.CssStyleDeclaration style = _element.style;
    style
      ..fontSize = '${fontSize.floor()}px'
      ..fontFamily = canonicalizeFontFamily(fontFamily);

    final double? height = textHeightStyle.height;
    if (height != null) {
      style.lineHeight = height.toString();
    }
    _invalidateBoundsCache();
  }

  /// Appends element and probe to hostElement that is set up for a specific
  /// TextStyle.
  void appendToHost(html.HtmlElement hostElement) {
    hostElement.append(_element);
    _invalidateBoundsCache();
  }

  html.Rectangle<num> _readAndCacheMetrics() =>
      _cachedBoundingClientRect ??= _element.getBoundingClientRect();

  /// The width of the paragraph being measured.
  double get width => _readAndCacheMetrics().width as double;

  /// The height of the paragraph being measured.
  double get height {
    double cachedHeight = _readAndCacheMetrics().height as double;
    if (browserEngine == BrowserEngine.firefox &&
      // In the flutter tester environment, we use a predictable-size for font
      // measurement tests.
      !ui.debugEmulateFlutterTesterEnvironment) {
      // See subpixel rounding bug :
      // https://bugzilla.mozilla.org/show_bug.cgi?id=442139
      // This causes bottom of letters such as 'y' to be cutoff and
      // incorrect rendering of double underlines.
      cachedHeight += 1.0;
    }
    return cachedHeight;
  }
}

/// Performs height measurement for the given [textHeightStyle].
///
/// The two results of this ruler's measurement are:
///
/// 1. [alphabeticBaseline].
/// 2. [height].
class TextHeightRuler {
  TextHeightRuler(this.textHeightStyle, this.rulerHost);

  final TextHeightStyle textHeightStyle;
  final RulerHost rulerHost;

  // Elements used to measure the line-height metric.
  late final html.HtmlElement _probe = _createProbe();
  late final html.HtmlElement _host = _createHost();
  final TextDimensions _dimensions = TextDimensions(html.ParagraphElement());

  /// The alphabetic baseline for this ruler's [textHeightStyle].
  late final double alphabeticBaseline = _probe.getBoundingClientRect().bottom.toDouble();

  /// The height for this ruler's [textHeightStyle].
  late final double height = _dimensions.height;

  /// Disposes of this ruler and detaches it from the DOM tree.
  void dispose() {
    _host.remove();
  }

  html.HtmlElement _createHost() {
    final html.DivElement host = html.DivElement();
    host.style
      ..visibility = 'hidden'
      ..position = 'absolute'
      ..top = '0'
      ..left = '0'
      ..display = 'flex'
      ..flexDirection = 'row'
      ..alignItems = 'baseline'
      ..margin = '0'
      ..border = '0'
      ..padding = '0';

    if (assertionsEnabled) {
      host.setAttribute('data-ruler', 'line-height');
    }

    _dimensions.applyHeightStyle(textHeightStyle);

    // Force single-line (even if wider than screen) and preserve whitespaces.
    _dimensions._element.style.whiteSpace = 'pre';

    // To measure line-height, all we need is a whitespace.
    _dimensions.updateTextToSpace();

    _dimensions.appendToHost(host);
    rulerHost.addElement(host);
    return host;
  }

  html.HtmlElement _createProbe() {
    final html.HtmlElement probe = html.DivElement();
    _host.append(probe);
    return probe;
  }
}

/// Performs 4 types of measurements:
///
/// 1. Single line: can be prepared by calling [measureAsSingleLine].
///    Measurement values will be available at [singleLineDimensions].
///
/// 2. Minimum intrinsic width: can be prepared by calling
///    [measureMinIntrinsicWidth]. Measurement values will be available at
///    [minIntrinsicDimensions].
///
/// 3. Constrained: can be prepared by calling [measureWithConstraints] and
///    passing the constraints. Measurement values will be available at
///    [constrainedDimensions].
///
/// 4. Boxes: within a paragraph, it measures a list of text boxes that enclose
///    a given range of text.
///
/// For performance reasons, it's advised to use [measureAll] and then reading
/// whatever measurements are needed. This causes the browser to only reflow
/// once instead of many times.
///
/// The [measureAll] method performs the first 3 stateful measurements but not
/// the 4th one.
///
/// This class is both reusable and stateful. Use it carefully. The correct
/// usage is as follows:
///
/// * First, call [willMeasure] passing it the paragraph to be measured.
/// * Call any of the [measureAsSingleLine], [measureMinIntrinsicWidth],
///   [measureWithConstraints], or [measureAll], to prepare the respective
///   measurement. These methods can be called any number of times.
/// * Call [didMeasure] to indicate that you are done with the paragraph passed
///   to the [willMeasure] method.
///
/// It is safe to reuse this object as long as paragraphs passed to the
/// [measure] method have the same style.
///
/// The only stateless method provided by this class is [measureBoxesForRange]
/// that doesn't rely on [willMeasure] and [didMeasure] lifecycle methods.
///
/// This class optimizes for plain text paragraphs, which should constitute the
/// majority of paragraphs in typical apps.
class ParagraphRuler {
  /// The only style that this [ParagraphRuler] measures text.
  final ParagraphGeometricStyle style;

  /// A [RulerManager] owns the host DOM element that this ruler can add
  /// elements to.
  ///
  /// The [rulerManager] keeps a cache of multiple [ParagraphRuler] instances,
  /// but a [ParagraphRuler] can only belong to one [RulerManager].
  final RulerManager rulerManager;

  ParagraphRuler(this.style, this.rulerManager) {
    _configureSingleLineHostElements();
    _configureMinIntrinsicHostElements();
    _configureConstrainedHostElements();
  }

  /// The alphabetic baseline of the paragraph being measured.
  double get alphabeticBaseline => _textHeightRuler.alphabeticBaseline;

  // Elements used to measure single-line metrics.
  final html.DivElement _singleLineHost = html.DivElement();
  final TextDimensions singleLineDimensions =
      TextDimensions(html.ParagraphElement());

  // Elements used to measure minIntrinsicWidth.
  final html.DivElement _minIntrinsicHost = html.DivElement();
  TextDimensions minIntrinsicDimensions =
      TextDimensions(html.ParagraphElement());

  // Elements used to measure metrics under a width constraint.
  final html.DivElement _constrainedHost = html.DivElement();
  TextDimensions constrainedDimensions =
      TextDimensions(html.ParagraphElement());

  // Elements used to measure the line-height metric.
  late final TextHeightRuler _textHeightRuler =
      TextHeightRuler(style.textHeightStyle, rulerManager);
  double get lineHeight {
    return _textHeightRuler.height;
  }

  /// The number of times this ruler was used this frame.
  ///
  /// This value is used to determine which rulers are rarely used and should be
  /// evicted from the ruler cache.
  int get hitCount => _hitCount;
  int _hitCount = 0;

  /// This method should be called whenever this ruler is being used to perform
  /// measurements.
  ///
  /// It increases the hit count of this ruler which is used when clearing the
  /// [rulerManager]'s cache to find the least used rulers.
  void hit() {
    _hitCount++;
  }

  /// Resets the hit count back to zero.
  void resetHitCount() {
    _hitCount = 0;
  }

  /// Makes sure this ruler is not used again after it has been disposed of,
  /// which would indicate a bug.
  @visibleForTesting
  bool get debugIsDisposed => _debugIsDisposed;
  bool _debugIsDisposed = false;

  void _configureSingleLineHostElements() {
    _singleLineHost.style
      ..visibility = 'hidden'
      ..position = 'absolute'
      ..top = '0' // this is important as baseline == probe.bottom
      ..left = '0'
      ..display = 'flex'
      ..flexDirection = 'row'
      ..alignItems = 'baseline'
      ..margin = '0'
      ..border = '0'
      ..padding = '0';

    if (assertionsEnabled) {
      _singleLineHost.setAttribute('data-ruler', 'single-line');
    }

    singleLineDimensions.applyStyle(style);

    // Force single-line (even if wider than screen) and preserve whitespaces.
    singleLineDimensions._element.style.whiteSpace = 'pre';

    singleLineDimensions.appendToHost(_singleLineHost);
    rulerManager.addElement(_singleLineHost);
  }

  void _configureMinIntrinsicHostElements() {
    // Configure min intrinsic host elements.
    _minIntrinsicHost.style
      ..visibility = 'hidden'
      ..position = 'absolute'
      ..top = '0' // this is important as baseline == probe.bottom
      ..left = '0'
      ..display = 'flex'
      ..flexDirection = 'row'
      ..margin = '0'
      ..border = '0'
      ..padding = '0';

    if (assertionsEnabled) {
      _minIntrinsicHost.setAttribute('data-ruler', 'min-intrinsic');
    }

    minIntrinsicDimensions.applyStyle(style);

    // "flex: 0" causes the paragraph element to shrink horizontally, exposing
    // its minimum intrinsic width.
    minIntrinsicDimensions._element.style
      ..flex = '0'
      ..display = 'inline'
      // Preserve newlines, wrap text, remove end of line spaces.
      // Not using pre-wrap here since end of line space hang measurement
      // changed in Chrome 77 Beta.
      ..whiteSpace = 'pre-line';

    _minIntrinsicHost.append(minIntrinsicDimensions._element);
    rulerManager.addElement(_minIntrinsicHost);
  }

  void _configureConstrainedHostElements() {
    _constrainedHost.style
      ..visibility = 'hidden'
      ..position = 'absolute'
      ..top = '0' // this is important as baseline == probe.bottom
      ..left = '0'
      ..display = 'flex'
      ..flexDirection = 'row'
      ..alignItems = 'baseline'
      ..margin = '0'
      ..border = '0'
      ..padding = '0';

    if (assertionsEnabled) {
      _constrainedHost.setAttribute('data-ruler', 'constrained');
    }

    constrainedDimensions.applyStyle(style);
    final html.CssStyleDeclaration elementStyle =
        constrainedDimensions._element.style;
    elementStyle
      ..display = 'block'
      ..overflowWrap = 'break-word';

    if (style.ellipsis != null) {
      elementStyle
        ..overflow = 'hidden'
        ..textOverflow = 'ellipsis';
    }

    constrainedDimensions.appendToHost(_constrainedHost);
    rulerManager.addElement(_constrainedHost);
  }

  /// The paragraph being measured.
  DomParagraph? _paragraph;

  /// Prepares this ruler for measuring the given [paragraph].
  ///
  /// This method must be called before calling any of the `measure*` methods.
  void willMeasure(DomParagraph paragraph) {
    assert(paragraph != null); // ignore: unnecessary_null_comparison
    assert(() {
      if (_paragraph != null) {
        throw Exception(
            'Attempted to reuse a $ParagraphRuler but it is currently '
            'measuring another paragraph ($_paragraph). It is possible that ');
      }
      return true;
    }());
    assert(paragraph.debugHasSameRootStyle(style));
    _paragraph = paragraph;
  }

  /// Prepares all 3 measurements:
  /// 1. single line.
  /// 2. minimum intrinsic width.
  /// 3. constrained.
  void measureAll(ui.ParagraphConstraints constraints) {
    measureAsSingleLine();
    measureMinIntrinsicWidth();
    measureWithConstraints(constraints);
  }

  /// Lays out the paragraph in a single line, giving it infinite amount of
  /// horizontal space.
  ///
  /// Measures [width], [height], and [alphabeticBaseline].
  void measureAsSingleLine() {
    assert(!_debugIsDisposed);
    assert(_paragraph != null);

    // HACK(mdebbar): TextField uses an empty string to measure the line height,
    // which doesn't work. So we need to replace it with a whitespace. The
    // correct fix would be to do line height and baseline measurements and
    // cache them separately.
    if (_paragraph!.plainText == '') {
      singleLineDimensions.updateTextToSpace();
    } else {
      singleLineDimensions.updateText(_paragraph!, style);
    }
  }

  /// Lays out the paragraph inside a flex row and sets "flex: 0", which
  /// squeezes the paragraph, forcing it to occupy minimum intrinsic width.
  ///
  /// Measures [width] and [height].
  void measureMinIntrinsicWidth() {
    assert(!_debugIsDisposed);
    assert(_paragraph != null);

    minIntrinsicDimensions.updateText(_paragraph!, style);
  }

  /// Lays out the paragraph giving it a width constraint.
  ///
  /// Measures [width], [height], and [alphabeticBaseline].
  void measureWithConstraints(ui.ParagraphConstraints constraints) {
    assert(!_debugIsDisposed);
    assert(_paragraph != null);

    constrainedDimensions.updateText(_paragraph!, style);

    // The extra 0.5 is because sometimes the browser needs slightly more space
    // than the size it reports back. When that happens the text may be wrap
    // when we thought it didn't.
    constrainedDimensions.updateConstraintWidth(
      constraints.width + 0.5,
      style.ellipsis,
    );
  }

  List<ui.TextBox> measurePlaceholderBoxes() {
    assert(!_debugIsDisposed);

    final DomParagraph? paragraph = _paragraph;
    assert(paragraph != null);

    if (paragraph!.placeholderCount == 0) {
      return const <ui.TextBox>[];
    }

    final List<html.Element> placeholderElements =
        constrainedDimensions._element.querySelectorAll('.$placeholderClass');
    final List<ui.TextBox> boxes = <ui.TextBox>[];

    for (final html.Element element in placeholderElements) {
      final html.Rectangle<num> rect = element.getBoundingClientRect();
      boxes.add(ui.TextBox.fromLTRBD(
        rect.left as double,
        rect.top as double,
        rect.right as double,
        rect.bottom as double,
        paragraph.textDirection,
      ));
    }
    return boxes;
  }

  /// Returns text position in a paragraph that contains multiple
  /// nested spans given an offset.
  int hitTest(ui.ParagraphConstraints constraints, ui.Offset offset) {
    measureWithConstraints(constraints);
    // Get paragraph element root used to measure constrainedDimensions.
    final html.HtmlElement el = constrainedDimensions._element;
    final List<html.Node> textNodes = <html.Node>[];
    // Collect all text nodes (breadth first traversal).
    // Since there is no api to get bounds of text nodes directly we work
    // upwards and measure span elements and finally the paragraph.
    _collectTextNodes(el.childNodes, textNodes);
    // Hit test spans starting from leaf nodes up (backwards).
    for (int i = textNodes.length - 1; i >= 0; i--) {
      final html.Node node = textNodes[i];
      // Check if offset is within client rect bounds of text node's
      // parent element.
      final html.Element parent = node.parentNode! as html.Element;
      final html.Rectangle<num> bounds = parent.getBoundingClientRect();
      final double dx = offset.dx;
      final double dy = offset.dy;
      if (dx >= bounds.left &&
          dx < bounds.right &&
          dy >= bounds.top &&
          dy < bounds.bottom) {
        // We found the element bounds that contains offset.
        // Calculate text position for this node.
        return _countTextPosition(el.childNodes, textNodes[i]);
      }
    }
    return 0;
  }

  void _collectTextNodes(Iterable<html.Node> nodes, List<html.Node> textNodes) {
    if (nodes.isEmpty) {
      return;
    }
    final List<html.Node> childNodes = <html.Node>[];
    for (final html.Node node in nodes) {
      if (node.nodeType == html.Node.TEXT_NODE) {
        textNodes.add(node);
      }
      childNodes.addAll(node.childNodes);
    }
    _collectTextNodes(childNodes, textNodes);
  }

  int _countTextPosition(List<html.Node> nodes, html.Node endNode) {
    int position = 0;
    final List<html.Node> stack = nodes.reversed.toList();
    while (true) {
      final html.Node node = stack.removeLast();
      stack.addAll(node.childNodes.reversed);
      if (node == endNode) {
        break;
      }
      if (node.nodeType == html.Node.TEXT_NODE) {
        position += node.text!.length;
      }
    }
    return position;
  }

  /// Performs clean-up after a measurement is done, preparing this ruler for
  /// a future reuse.
  ///
  /// Call this method immediately after calling `measure*` methods for a
  /// particular [paragraph]. This ruler is not reusable until [didMeasure] is
  /// called.
  void didMeasure() {
    assert(_paragraph != null);
    // Remove any rich text we set during layout for the following reasons:
    // - there won't be any text for the browser to lay out when we commit the
    //   current frame.
    // - this keeps the cost of removing content together with the measurement
    //   in the profile. Otherwise, the cost of removing will be paid by a
    //   random next paragraph measured in the future, and make the performance
    //   profile hard to understand.
    //
    // We do not do this for plain text, because replacing plain text is more
    // expensive than paying the cost of the DOM mutation to clean it.
    if (_paragraph!.plainText == null) {
      domRenderer
        ..clearDom(singleLineDimensions._element)
        ..clearDom(minIntrinsicDimensions._element)
        ..clearDom(constrainedDimensions._element);
    }
    _paragraph = null;
  }

  /// Performs stateless measurement of text boxes for a given range of text.
  ///
  /// This method doesn't depend on [willMeasure] and [didMeasure] lifecycle
  /// methods.
  List<ui.TextBox> measureBoxesForRange(
    String plainText,
    ui.ParagraphConstraints constraints, {
    required int start,
    required int end,
    required double alignOffset,
    required ui.TextDirection textDirection,
  }) {
    assert(!_debugIsDisposed);
    assert(start >= 0 && start <= plainText.length);
    assert(end >= 0 && end <= plainText.length);
    assert(start <= end);

    final String before = plainText.substring(0, start);
    final String rangeText = plainText.substring(start, end);
    final String after = plainText.substring(end);

    final html.SpanElement rangeSpan = html.SpanElement()..text = rangeText;

    // Setup the [ruler.constrainedDimensions] element to be used for measurement.
    domRenderer.clearDom(constrainedDimensions._element);
    constrainedDimensions._element
      ..appendText(before)
      ..append(rangeSpan)
      ..appendText(after);
    constrainedDimensions.updateConstraintWidth(constraints.width, null);

    // Measure the rects of [rangeSpan].
    final List<html.Rectangle<num>> clientRects = rangeSpan.getClientRects();
    final List<ui.TextBox> boxes = <ui.TextBox>[];

    final double maxLinesLimit = style.maxLines == null
        ? double.infinity
        : style.maxLines! * lineHeight;

    html.Rectangle<num>? previousRect;
    for (final html.Rectangle<num> rect in clientRects) {
      // If [rect] is an empty box on the same line as the previous box, don't
      // include it in the result.
      if (rect.top == previousRect?.top && rect.left == rect.right) {
        continue;
      }
      // As soon as we go beyond [maxLines], stop adding boxes.
      if (rect.top >= maxLinesLimit) {
        break;
      }

      boxes.add(ui.TextBox.fromLTRBD(
        rect.left.toDouble() + alignOffset,
        rect.top as double,
        rect.right.toDouble() + alignOffset,
        rect.bottom as double,
        textDirection,
      ));
      previousRect = rect;
    }

    // Cleanup after measuring the boxes.
    domRenderer.clearDom(constrainedDimensions._element);
    return boxes;
  }

  /// Detaches this ruler from the DOM and makes it unusable for future
  /// measurements.
  ///
  /// Disposed rulers should be garbage collected after calling this method.
  void dispose() {
    assert(() {
      if (_paragraph != null) {
        throw Exception('Attempted to dispose of a ruler in the middle of '
            'measurement. This is likely a bug in the framework.');
      }
      return true;
    }());
    _singleLineHost.remove();
    _minIntrinsicHost.remove();
    _constrainedHost.remove();
    _textHeightRuler.dispose();
    assert(() {
      _debugIsDisposed = true;
      return true;
    }());
  }

  // Bounded cache for text measurement for a particular width constraint.
  Map<String?, List<MeasurementResult?>> _measurementCache =
      <String?, List<MeasurementResult?>>{};
  // Mru list for cache.
  final List<String?> _mruList = <String?>[];
  static const int _cacheLimit = 2400;
  // Number of items to evict when cache limit is reached.
  static const int _cacheBlockFactor = 100;
  // Number of constraint results per unique text item.
  // This limit prevents growth during animation where the size of a container
  // is changing.
  static const int _constraintCacheSize = 8;

  void cacheMeasurement(DomParagraph paragraph, MeasurementResult? item) {
    final String? plainText = paragraph.plainText;
    final List<MeasurementResult?> constraintCache =
        _measurementCache[plainText] ??= <MeasurementResult?>[];
    constraintCache.add(item);
    if (constraintCache.length > _constraintCacheSize) {
      constraintCache.removeAt(0);
    }
    _mruList.add(plainText);
    if (_mruList.length > _cacheLimit) {
      // Evict a range.
      for (int i = 0; i < _cacheBlockFactor; i++) {
        _measurementCache.remove(_mruList[i]);
      }
      _mruList.removeRange(0, _cacheBlockFactor);
    }
  }

  MeasurementResult? cacheLookup(
      DomParagraph paragraph, ui.ParagraphConstraints constraints) {
    final String? plainText = paragraph.plainText;
    if (plainText == null) {
      // Multi span paragraph, do not use cache item.
      return null;
    }
    final List<MeasurementResult?>? constraintCache =
        _measurementCache[plainText];
    if (constraintCache == null) {
      return null;
    }
    final int len = constraintCache.length;
    for (int i = 0; i < len; i++) {
      final MeasurementResult item = constraintCache[i]!;
      if (item.constraintWidth == constraints.width &&
          item.textAlign == paragraph.textAlign &&
          item.textDirection == paragraph.textDirection) {
        return item;
      }
    }
    return null;
  }
}

/// The result that contains all measurements of a paragraph at the given
/// constraint width.
@immutable
class MeasurementResult {
  /// The width that was given as a constraint when the paragraph was laid out.
  final double constraintWidth;

  /// Whether the paragraph can fit in a single line given [constraintWidth].
  final bool isSingleLine;

  /// The amount of horizontal space the paragraph occupies.
  final double width;

  /// The amount of vertical space the paragraph occupies.
  final double height;

  /// {@macro dart.ui.paragraph.naturalHeight}
  ///
  /// When [ParagraphGeometricStyle.maxLines] is null, [naturalHeight] and
  /// [height] should be equal.
  final double naturalHeight;

  /// The amount of vertical space each line of the paragraph occupies.
  ///
  /// In some cases, measuring [lineHeight] is unnecessary, so it's nullable. If
  /// present, it should be equal to [height] when [isSingleLine] is true.
  final double? lineHeight;

  /// {@macro dart.ui.paragraph.minIntrinsicWidth}
  final double minIntrinsicWidth;

  /// {@macro dart.ui.paragraph.maxIntrinsicWidth}
  final double maxIntrinsicWidth;

  /// {@macro dart.ui.paragraph.alphabeticBaseline}
  final double alphabeticBaseline;

  /// {@macro dart.ui.paragraph.ideographicBaseline}
  final double ideographicBaseline;

  /// The full list of [EngineLineMetrics] that describe in detail the various metrics
  /// of each laid out line.
  final List<EngineLineMetrics>? lines;

  final List<ui.TextBox> placeholderBoxes;

  /// The text align value of the paragraph.
  final ui.TextAlign textAlign;

  /// The text direction of the paragraph.
  final ui.TextDirection textDirection;

  MeasurementResult(
    this.constraintWidth, {
    required this.isSingleLine,
    required this.width,
    required this.height,
    required this.naturalHeight,
    required this.lineHeight,
    required this.minIntrinsicWidth,
    required this.maxIntrinsicWidth,
    required this.alphabeticBaseline,
    required this.ideographicBaseline,
    required this.lines,
    required this.placeholderBoxes,
    required ui.TextAlign? textAlign,
    required ui.TextDirection? textDirection,
  })  : assert(constraintWidth != null), // ignore: unnecessary_null_comparison
        assert(isSingleLine != null), // ignore: unnecessary_null_comparison
        assert(width != null), // ignore: unnecessary_null_comparison
        assert(height != null), // ignore: unnecessary_null_comparison
        assert(naturalHeight != null), // ignore: unnecessary_null_comparison
        assert(minIntrinsicWidth != null), // ignore: unnecessary_null_comparison
        assert(maxIntrinsicWidth != null), // ignore: unnecessary_null_comparison
        assert(alphabeticBaseline != null), // ignore: unnecessary_null_comparison
        assert(ideographicBaseline != null), // ignore: unnecessary_null_comparison
        this.textAlign = textAlign ?? ui.TextAlign.start,// ignore: unnecessary_this
        this.textDirection = textDirection ?? ui.TextDirection.ltr;// ignore: unnecessary_this
}
