// 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:math' as math;
import 'dart:typed_data';

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

import '../../engine.dart'  show registerHotRestartListener;
import '../alarm_clock.dart';
import '../browser_detection.dart';
import '../configuration.dart';
import '../dom.dart';
import '../platform_dispatcher.dart';
import '../util.dart';
import '../vector_math.dart';
import '../window.dart';
import 'accessibility.dart';
import 'checkable.dart';
import 'dialog.dart';
import 'focusable.dart';
import 'image.dart';
import 'incrementable.dart';
import 'label_and_value.dart';
import 'link.dart';
import 'live_region.dart';
import 'platform_view.dart';
import 'scrollable.dart';
import 'semantics_helper.dart';
import 'tappable.dart';
import 'text_field.dart';

class EngineAccessibilityFeatures implements ui.AccessibilityFeatures {
  const EngineAccessibilityFeatures(this._index);

  static const int _kAccessibleNavigation = 1 << 0;
  static const int _kInvertColorsIndex = 1 << 1;
  static const int _kDisableAnimationsIndex = 1 << 2;
  static const int _kBoldTextIndex = 1 << 3;
  static const int _kReduceMotionIndex = 1 << 4;
  static const int _kHighContrastIndex = 1 << 5;
  static const int _kOnOffSwitchLabelsIndex = 1 << 6;

  // A bitfield which represents each enabled feature.
  final int _index;

  @override
  bool get accessibleNavigation => _kAccessibleNavigation & _index != 0;
  @override
  bool get invertColors => _kInvertColorsIndex & _index != 0;
  @override
  bool get disableAnimations => _kDisableAnimationsIndex & _index != 0;
  @override
  bool get boldText => _kBoldTextIndex & _index != 0;
  @override
  bool get reduceMotion => _kReduceMotionIndex & _index != 0;
  @override
  bool get highContrast => _kHighContrastIndex & _index != 0;
  @override
  bool get onOffSwitchLabels => _kOnOffSwitchLabelsIndex & _index != 0;

  @override
  String toString() {
    final List<String> features = <String>[];
    if (accessibleNavigation) {
      features.add('accessibleNavigation');
    }
    if (invertColors) {
      features.add('invertColors');
    }
    if (disableAnimations) {
      features.add('disableAnimations');
    }
    if (boldText) {
      features.add('boldText');
    }
    if (reduceMotion) {
      features.add('reduceMotion');
    }
    if (highContrast) {
      features.add('highContrast');
    }
    if (onOffSwitchLabels) {
      features.add('onOffSwitchLabels');
    }
    return 'AccessibilityFeatures$features';
  }

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is EngineAccessibilityFeatures && other._index == _index;
  }

  @override
  int get hashCode => _index.hashCode;

  EngineAccessibilityFeatures copyWith({
      bool? accessibleNavigation,
      bool? invertColors,
      bool? disableAnimations,
      bool? boldText,
      bool? reduceMotion,
      bool? highContrast,
      bool? onOffSwitchLabels})
  {
    final EngineAccessibilityFeaturesBuilder builder = EngineAccessibilityFeaturesBuilder(0);

    builder.accessibleNavigation = accessibleNavigation ?? this.accessibleNavigation;
    builder.invertColors = invertColors ?? this.invertColors;
    builder.disableAnimations = disableAnimations ?? this.disableAnimations;
    builder.boldText = boldText ?? this.boldText;
    builder.reduceMotion = reduceMotion ?? this.reduceMotion;
    builder.highContrast = highContrast ?? this.highContrast;
    builder.onOffSwitchLabels = onOffSwitchLabels ?? this.onOffSwitchLabels;

    return builder.build();
  }
}

class EngineAccessibilityFeaturesBuilder {
  EngineAccessibilityFeaturesBuilder(this._index);

  int _index = 0;

  bool get accessibleNavigation => EngineAccessibilityFeatures._kAccessibleNavigation & _index != 0;
  bool get invertColors => EngineAccessibilityFeatures._kInvertColorsIndex & _index != 0;
  bool get disableAnimations => EngineAccessibilityFeatures._kDisableAnimationsIndex & _index != 0;
  bool get boldText => EngineAccessibilityFeatures._kBoldTextIndex & _index != 0;
  bool get reduceMotion => EngineAccessibilityFeatures._kReduceMotionIndex & _index != 0;
  bool get highContrast => EngineAccessibilityFeatures._kHighContrastIndex & _index != 0;
  bool get onOffSwitchLabels => EngineAccessibilityFeatures._kOnOffSwitchLabelsIndex & _index != 0;

  set accessibleNavigation(bool value) {
    const int accessibleNavigation = EngineAccessibilityFeatures._kAccessibleNavigation;
    _index = value? _index | accessibleNavigation : _index & ~accessibleNavigation;
  }

  set invertColors(bool value) {
    const int invertColors = EngineAccessibilityFeatures._kInvertColorsIndex;
    _index = value? _index | invertColors : _index & ~invertColors;
  }

  set disableAnimations(bool value) {
    const int disableAnimations = EngineAccessibilityFeatures._kDisableAnimationsIndex;
    _index = value? _index | disableAnimations : _index & ~disableAnimations;
  }

  set boldText(bool value) {
    const int boldText = EngineAccessibilityFeatures._kBoldTextIndex;
    _index = value? _index | boldText : _index & ~boldText;
  }

  set reduceMotion(bool value) {
    const int reduceMotion = EngineAccessibilityFeatures._kReduceMotionIndex;
    _index = value? _index | reduceMotion : _index & ~reduceMotion;
  }

  set highContrast(bool value) {
    const int highContrast = EngineAccessibilityFeatures._kHighContrastIndex;
    _index = value? _index | highContrast : _index & ~highContrast;
  }

  set onOffSwitchLabels(bool value) {
    const int onOffSwitchLabels = EngineAccessibilityFeatures._kOnOffSwitchLabelsIndex;
    _index = value? _index | onOffSwitchLabels : _index & ~onOffSwitchLabels;
  }

  /// Creates and returns an instance of EngineAccessibilityFeatures based on the value of _index
  EngineAccessibilityFeatures build() {
    return EngineAccessibilityFeatures(_index);
  }
}

/// Contains updates for the semantics tree.
///
/// This class provides private engine-side API that's not available in the
/// `dart:ui` [ui.SemanticsUpdate].
class SemanticsUpdate implements ui.SemanticsUpdate {
  SemanticsUpdate({List<SemanticsNodeUpdate>? nodeUpdates})
      : _nodeUpdates = nodeUpdates;

  /// Updates for individual nodes.
  final List<SemanticsNodeUpdate>? _nodeUpdates;

  @override
  void dispose() {
    // Intentionally left blank. This method exists for API compatibility with
    // Flutter, but it is not required as memory resource management is handled
    // by JavaScript's garbage collector.
  }
}

/// Updates the properties of a particular semantics node.
class SemanticsNodeUpdate {
  SemanticsNodeUpdate({
    required this.id,
    required this.flags,
    required this.actions,
    required this.maxValueLength,
    required this.currentValueLength,
    required this.textSelectionBase,
    required this.textSelectionExtent,
    required this.platformViewId,
    required this.scrollChildren,
    required this.scrollIndex,
    required this.scrollPosition,
    required this.scrollExtentMax,
    required this.scrollExtentMin,
    required this.rect,
    required this.identifier,
    required this.label,
    required this.labelAttributes,
    required this.hint,
    required this.hintAttributes,
    required this.value,
    required this.valueAttributes,
    required this.increasedValue,
    required this.increasedValueAttributes,
    required this.decreasedValue,
    required this.decreasedValueAttributes,
    this.tooltip,
    this.textDirection,
    required this.transform,
    required this.elevation,
    required this.thickness,
    required this.childrenInTraversalOrder,
    required this.childrenInHitTestOrder,
    required this.additionalActions,
  });

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final int id;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final int flags;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final int actions;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final int maxValueLength;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final int currentValueLength;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final int textSelectionBase;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final int textSelectionExtent;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final int platformViewId;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final int scrollChildren;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final int scrollIndex;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final double scrollPosition;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final double scrollExtentMax;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final double scrollExtentMin;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final ui.Rect rect;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final String identifier;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final String label;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final List<ui.StringAttribute> labelAttributes;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final String hint;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final List<ui.StringAttribute> hintAttributes;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final String value;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final List<ui.StringAttribute> valueAttributes;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final String increasedValue;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final List<ui.StringAttribute> increasedValueAttributes;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final String decreasedValue;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final List<ui.StringAttribute> decreasedValueAttributes;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final String? tooltip;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final ui.TextDirection? textDirection;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final Float32List transform;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final Int32List childrenInTraversalOrder;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final Int32List childrenInHitTestOrder;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final Int32List additionalActions;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final double elevation;

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  final double thickness;
}

/// Identifies [PrimaryRoleManager] implementations.
///
/// Each value corresponds to the most specific role a semantics node plays in
/// the semantics tree.
enum PrimaryRole {
  /// Supports incrementing and/or decrementing its value.
  incrementable,

  /// Able to scroll its contents vertically or horizontally.
  scrollable,

  /// Accepts tap or click gestures.
  button,

  /// Contains editable text.
  textField,

  /// A control that has a checked state, such as a check box or a radio button.
  checkable,

  /// Visual only element.
  image,

  /// Adds the "dialog" ARIA role to the node.
  ///
  /// This corresponds to a semantics node that has `scopesRoute` bit set. While
  /// in Flutter a named route is not necessarily a dialog, this is the closest
  /// analog on the web.
  ///
  /// There are 3 possible situations:
  ///
  /// * The node also has the `namesRoute` bit set. This means that the node's
  ///   `label` describes the dialog, which can be expressed by adding the
  ///   `aria-label` attribute.
  /// * A descendant node has the `namesRoute` bit set. This means that the
  ///   child's content describes the dialog. The child may simply be labelled,
  ///   or it may be a subtree of nodes that describe the dialog together. The
  ///   nearest HTML equivalent is `aria-describedby`. The child acquires the
  ///   [routeName] role, which manages the relevant ARIA attributes.
  /// * There is no `namesRoute` bit anywhere in the sub-tree rooted at the
  ///   current node. In this case it's likely not a dialog at all, and the node
  ///   should not get a label or the "dialog" role. It's just a group of
  ///   children. For example, a modal barrier has `scopesRoute` set but marking
  ///   it as a dialog would be wrong.
  dialog,

  /// The node's primary role is to host a platform view.
  platformView,

  /// A role used when a more specific role cannot be assigend to
  /// a [SemanticsObject].
  ///
  /// Provides a label or a value.
  generic,

  /// Contains a link.
  link,
}

/// Identifies one of the secondary [RoleManager]s of a [PrimaryRoleManager].
enum Role {
  /// Supplies generic accessibility focus features to semantics nodes that have
  /// [ui.SemanticsFlag.isFocusable] set.
  focusable,

  /// Supplies generic tapping/clicking functionality.
  tappable,

  /// Provides an `aria-label` from `label`, `value`, and/or `tooltip` values.
  ///
  /// The two are combined into the same role because they interact with each
  /// other.
  labelAndValue,

  /// Contains a region whose changes will be announced to the screen reader
  /// without having to be in focus.
  ///
  /// These regions can be a snackbar or a text field error. Once identified
  /// with this role, they will be able to get the assistive technology's
  /// attention right away.
  liveRegion,

  /// Provides a description for an ancestor dialog.
  ///
  /// This role is assigned to nodes that have `namesRoute` set but not
  /// `scopesRoute`. When both flags are set the node only gets the dialog
  /// role (see [dialog]).
  ///
  /// If the ancestor dialog is missing, this role does nothing useful.
  routeName,
}

/// Responsible for setting the `role` ARIA attribute and for attaching zero or
/// more secondary [RoleManager]s to a [SemanticsObject].
abstract class PrimaryRoleManager {
  /// Initializes a role for a [semanticsObject] that includes basic
  /// functionality for focus, labels, live regions, and route names.
  ///
  /// If `labelRepresentation` is true, configures the [LabelAndValue] role with
  /// [LabelAndValue.labelRepresentation] set to true.
  PrimaryRoleManager.withBasics(this.role, this.semanticsObject, { required LeafLabelRepresentation labelRepresentation }) {
    element = _initElement(createElement(), semanticsObject);
    addFocusManagement();
    addLiveRegion();
    addRouteName();
    addLabelAndValue(labelRepresentation: labelRepresentation);
  }

  /// Initializes a blank role for a [semanticsObject].
  ///
  /// Use this constructor for highly specialized cases where
  /// [RoleManager.withBasics] does not work, for example when the default focus
  /// management intereferes with the widget's functionality.
  PrimaryRoleManager.blank(this.role, this.semanticsObject) {
    element = _initElement(createElement(), semanticsObject);
  }

  late final DomElement element;

  /// The primary role identifier.
  final PrimaryRole role;

  /// The semantics object managed by this role.
  final SemanticsObject semanticsObject;

  /// Secondary role managers, if any.
  List<RoleManager>? get secondaryRoleManagers => _secondaryRoleManagers;
  List<RoleManager>? _secondaryRoleManagers;

  /// Identifiers of secondary roles used by this primary role manager.
  ///
  /// This is only meant to be used in tests.
  @visibleForTesting
  List<Role> get debugSecondaryRoles => _secondaryRoleManagers?.map((RoleManager manager) => manager.role).toList() ?? const <Role>[];

  @protected
  DomElement createElement() => domDocument.createElement('flt-semantics');

  static DomElement _initElement(DomElement element, SemanticsObject semanticsObject) {
    // DOM nodes created for semantics objects are positioned absolutely using
    // transforms.
    element.style.position = 'absolute';
    element.setAttribute('id', 'flt-semantic-node-${semanticsObject.id}');

    // The root node has some properties that other nodes do not.
    if (semanticsObject.id == 0 && !configuration.debugShowSemanticsNodes) {
      // Make all semantics transparent. Use `filter` instead of `opacity`
      // attribute because `filter` is stronger. `opacity` does not apply to
      // some elements, particularly on iOS, such as the slider thumb and track.
      //
      // Use transparency instead of "visibility:hidden" or "display:none"
      // so that a screen reader does not ignore these elements.
      element.style.filter = 'opacity(0%)';

      // Make text explicitly transparent to signal to the browser that no
      // rasterization needs to be done.
      element.style.color = 'rgba(0,0,0,0)';
    }

    // Make semantic elements visible for debugging by outlining them using a
    // green border. Do not use `border` attribute because it affects layout
    // (`outline` does not).
    if (configuration.debugShowSemanticsNodes) {
      element.style.outline = '1px solid green';
    }
    return element;
  }

  /// Sets the `role` ARIA attribute.
  void setAriaRole(String ariaRoleName) {
    setAttribute('role', ariaRoleName);
  }

  /// Sets the `role` ARIA attribute.
  void setAttribute(String name, Object value) {
    element.setAttribute(name, value);
  }

  void append(DomElement child) {
    element.append(child);
  }

  void removeAttribute(String name) => element.removeAttribute(name);

  void addEventListener(String type, DomEventListener? listener, [bool? useCapture]) => element.addEventListener(type, listener, useCapture);

  void removeEventListener(String type, DomEventListener? listener, [bool? useCapture]) => element.removeEventListener(type, listener, useCapture);

  /// Convenience getter for the [Focusable] role manager, if any.
  Focusable? get focusable => _focusable;
  Focusable? _focusable;

  /// Adds generic focus management features.
  void addFocusManagement() {
    addSecondaryRole(_focusable = Focusable(semanticsObject, this));
  }

  /// Adds generic live region features.
  void addLiveRegion() {
    addSecondaryRole(LiveRegion(semanticsObject, this));
  }

  /// Adds generic route name features.
  void addRouteName() {
    addSecondaryRole(RouteName(semanticsObject, this));
  }

  /// Adds generic label features.
  void addLabelAndValue({ required LeafLabelRepresentation labelRepresentation }) {
    addSecondaryRole(LabelAndValue(semanticsObject, this, labelRepresentation: labelRepresentation));
  }

  /// Adds generic functionality for handling taps and clicks.
  void addTappable() {
    addSecondaryRole(Tappable(semanticsObject, this));
  }

  /// Adds a secondary role to this primary role manager.
  ///
  /// This method should be called by concrete implementations of
  /// [PrimaryRoleManager] during initialization.
  @protected
  void addSecondaryRole(RoleManager secondaryRoleManager) {
    assert(
      _secondaryRoleManagers?.any((RoleManager manager) => manager.role == secondaryRoleManager.role) != true,
      'Cannot add secondary role ${secondaryRoleManager.role}. This object already has this secondary role.',
    );
    _secondaryRoleManagers ??= <RoleManager>[];
    _secondaryRoleManagers!.add(secondaryRoleManager);
  }

  /// Called immediately after the fields of the [semanticsObject] are updated
  /// by a [SemanticsUpdate].
  ///
  /// A concrete implementation of this method would typically use some of the
  /// "is*Dirty" getters to find out exactly what's changed and apply the
  /// minimum DOM updates.
  ///
  /// The base implementation requests every secondary role manager to update
  /// the object.
  @mustCallSuper
  void update() {
    final List<RoleManager>? secondaryRoles = _secondaryRoleManagers;
    if (secondaryRoles == null) {
      return;
    }
    for (final RoleManager secondaryRole in secondaryRoles) {
      secondaryRole.update();
    }
  }

  /// Whether this role manager was disposed of.
  bool get isDisposed => _isDisposed;
  bool _isDisposed = false;

  /// Called when [semanticsObject] is removed, or when it changes its role such
  /// that this role is no longer relevant.
  ///
  /// This method is expected to remove role-specific functionality from the
  /// DOM. In particular, this method is the appropriate place to call
  /// [EngineSemanticsOwner.removeGestureModeListener] if this role reponds to
  /// gesture mode changes.
  @mustCallSuper
  void dispose() {
    removeAttribute('role');
    _isDisposed = true;
  }

  /// Transfers the accessibility focus to the [element] managed by this role
  /// manager as a result of this node taking focus by default.
  ///
  /// For example, when a dialog pops up it is expected that one of its child
  /// nodes takes accessibility focus.
  ///
  /// Transferring accessibility focus is different from transferring input
  /// focus. Not all elements that can take accessibility focus can also take
  /// input focus. For example, a plain text node cannot take input focus, but
  /// it can take accessibility focus.
  ///
  /// Returns `true` if the role manager took the focus. Returns `false` if
  /// this role manager did not take the focus. The return value can be used to
  /// decide whether to stop searching for a node that should take focus.
  bool focusAsRouteDefault();
}

/// A role used when a more specific role couldn't be assigned to the node.
final class GenericRole extends PrimaryRoleManager {
  GenericRole(SemanticsObject semanticsObject) : super.withBasics(
    PrimaryRole.generic,
    semanticsObject,
    labelRepresentation: LeafLabelRepresentation.domText,
  ) {
    // Typically a tappable widget would have a more specific role, such as
    // "link", "button", "checkbox", etc. However, there are situations when a
    // tappable is not a leaf node, but contains other nodes, which can also be
    // tappable. For example, the dismiss barrier of a pop-up menu is a tappable
    // ancestor of the menu itself, while the menu may contain tappable
    // children.
    if (semanticsObject.isTappable) {
      addTappable();
    }
  }

  @override
  void update() {
    super.update();

    if (!semanticsObject.hasLabel) {
      // The node didn't get a more specific role, and it has no label. It is
      // likely that this node is simply there for positioning its children and
      // has no other role for the screen reader to be aware of. In this case,
      // the element does not need a `role` attribute at all.
      return;
    }

    // Assign one of three roles to the element: heading, group, text.
    //
    // - "group" is used when the node has children, irrespective of whether the
    //   node is marked as a header or not. This is because marking a group
    //   as a "heading" will prevent the AT from reaching its children.
    // - "heading" is used when the framework explicitly marks the node as a
    //   heading and the node does not have children.
    // - "text" is used by default.
    //
    // As of October 24, 2022, "text" only has effect on Safari. Other browsers
    // ignore it. Setting role="text" prevents Safari from treating the element
    // as a "group" or "empty group". Other browsers still announce it as
    // "group" or "empty group". However, other options considered produced even
    // worse results, such as:
    //
    // - Ignore the size of the element and size the focus ring to the text
    //   content, which is wrong. The HTML text size is irrelevant because
    //   Flutter renders into canvas, so the focus ring looks wrong.
    // - Read out the same label multiple times.
    if (semanticsObject.hasChildren) {
      setAriaRole('group');
    } else if (semanticsObject.hasFlag(ui.SemanticsFlag.isHeader)) {
      setAriaRole('heading');
    } else {
      setAriaRole('text');
    }
  }

  @override
  bool focusAsRouteDefault() {
    // Case 1: current node has input focus. Let the input focus system decide
    // default focusability.
    if (semanticsObject.isFocusable) {
      final Focusable? focusable = this.focusable;
      if (focusable != null) {
        return focusable.focusAsRouteDefault();
      }
    }

    // Case 2: current node is not focusable, but just a container of other
    // nodes or lacks a label. Do not focus on it and let the search continue.
    if (semanticsObject.hasChildren || !semanticsObject.hasLabel) {
      return false;
    }

    // Case 3: current node is visual/informational. Move just the
    // accessibility focus.

    // Plain text nodes should not be focusable via keyboard or mouse. They are
    // only focusable for the purposes of focusing the screen reader. To achieve
    // this the -1 value is used.
    //
    // See also:
    //
    // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
    element.tabIndex = -1;
    element.focus();
    return true;
  }
}

/// Provides a piece of functionality to a [SemanticsObject].
///
/// A secondary role must not set the `role` ARIA attribute. That responsibility
/// falls on the [PrimaryRoleManager]. One [SemanticsObject] may have more than
/// one [RoleManager] but an element may only have one ARIA role, so setting the
/// `role` attribute from a [RoleManager] would cause conflicts.
///
/// The [PrimaryRoleManager] decides the list of [RoleManager]s a given semantics
/// node should use.
abstract class RoleManager {
  /// Initializes a secondary role for [semanticsObject].
  ///
  /// A single role object manages exactly one [SemanticsObject].
  RoleManager(this.role, this.semanticsObject, this.owner);

  /// Role identifier.
  final Role role;

  /// The semantics object managed by this role.
  final SemanticsObject semanticsObject;

  final PrimaryRoleManager owner;

  /// Called immediately after the [semanticsObject] updates some of its fields.
  ///
  /// A concrete implementation of this method would typically use some of the
  /// "is*Dirty" getters to find out exactly what's changed and apply the
  /// minimum DOM updates.
  void update();

  /// Whether this role manager was disposed of.
  bool get isDisposed => _isDisposed;
  bool _isDisposed = false;

  /// Called when [semanticsObject] is removed, or when it changes its role such
  /// that this role is no longer relevant.
  ///
  /// This method is expected to remove role-specific functionality from the
  /// DOM. In particular, this method is the appropriate place to call
  /// [EngineSemanticsOwner.removeGestureModeListener] if this role reponds to
  /// gesture mode changes.
  @mustCallSuper
  void dispose() {
    _isDisposed = true;
  }
}

/// Instantiation of a framework-side semantics node in the DOM.
///
/// Instances of this class are retained from frame to frame. Each instance is
/// permanently attached to an [id] and a DOM [element] used to convey semantics
/// information to the browser.
class SemanticsObject {
  /// Creates a semantics tree node with the given [id] and [owner].
  SemanticsObject(this.id, this.owner);

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  int get flags => _flags;
  int _flags = 0;

  /// Whether the [flags] field has been updated but has not been applied to the
  /// DOM yet.
  bool get isFlagsDirty => _isDirty(_flagsIndex);
  static const int _flagsIndex = 1 << 0;
  void _markFlagsDirty() {
    _dirtyFields |= _flagsIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  int? get actions => _actions;
  int? _actions;

  static const int _actionsIndex = 1 << 1;

  /// Whether the [actions] field has been updated but has not been applied to
  /// the DOM yet.
  bool get isActionsDirty => _isDirty(_actionsIndex);
  void _markActionsDirty() {
    _dirtyFields |= _actionsIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  int? get textSelectionBase => _textSelectionBase;
  int? _textSelectionBase;

  static const int _textSelectionBaseIndex = 1 << 2;

  /// Whether the [textSelectionBase] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isTextSelectionBaseDirty => _isDirty(_textSelectionBaseIndex);
  void _markTextSelectionBaseDirty() {
    _dirtyFields |= _textSelectionBaseIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  int? get textSelectionExtent => _textSelectionExtent;
  int? _textSelectionExtent;

  static const int _textSelectionExtentIndex = 1 << 3;

  /// Whether the [textSelectionExtent] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isTextSelectionExtentDirty => _isDirty(_textSelectionExtentIndex);
  void _markTextSelectionExtentDirty() {
    _dirtyFields |= _textSelectionExtentIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  int? get scrollChildren => _scrollChildren;
  int? _scrollChildren;

  static const int _scrollChildrenIndex = 1 << 4;

  /// Whether the [scrollChildren] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isScrollChildrenDirty => _isDirty(_scrollChildrenIndex);
  void _markScrollChildrenDirty() {
    _dirtyFields |= _scrollChildrenIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  int? get scrollIndex => _scrollIndex;
  int? _scrollIndex;

  static const int _scrollIndexIndex = 1 << 5;

  /// Whether the [scrollIndex] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isScrollIndexDirty => _isDirty(_scrollIndexIndex);
  void _markScrollIndexDirty() {
    _dirtyFields |= _scrollIndexIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  double? get scrollPosition => _scrollPosition;
  double? _scrollPosition;

  static const int _scrollPositionIndex = 1 << 6;

  /// Whether the [scrollPosition] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isScrollPositionDirty => _isDirty(_scrollPositionIndex);
  void _markScrollPositionDirty() {
    _dirtyFields |= _scrollPositionIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  double? get scrollExtentMax => _scrollExtentMax;
  double? _scrollExtentMax;

  static const int _scrollExtentMaxIndex = 1 << 7;

  /// Whether the [scrollExtentMax] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isScrollExtentMaxDirty => _isDirty(_scrollExtentMaxIndex);
  void _markScrollExtentMaxDirty() {
    _dirtyFields |= _scrollExtentMaxIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  double? get scrollExtentMin => _scrollExtentMin;
  double? _scrollExtentMin;

  static const int _scrollExtentMinIndex = 1 << 8;

  /// Whether the [scrollExtentMin] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isScrollExtentMinDirty => _isDirty(_scrollExtentMinIndex);
  void _markScrollExtentMinDirty() {
    _dirtyFields |= _scrollExtentMinIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  ui.Rect? get rect => _rect;
  ui.Rect? _rect;

  static const int _rectIndex = 1 << 9;

  /// Whether the [rect] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isRectDirty => _isDirty(_rectIndex);
  void _markRectDirty() {
    _dirtyFields |= _rectIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  String? get label => _label;
  String? _label;

  /// See [ui.SemanticsUpdateBuilder.updateNode]
  List<ui.StringAttribute>? get labelAttributes => _labelAttributes;
  List<ui.StringAttribute>? _labelAttributes;

  /// Whether this object contains a non-empty label.
  bool get hasLabel => _label != null && _label!.isNotEmpty;

  static const int _labelIndex = 1 << 10;

  /// Whether the [label] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isLabelDirty => _isDirty(_labelIndex);
  void _markLabelDirty() {
    _dirtyFields |= _labelIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  String? get hint => _hint;
  String? _hint;

  /// See [ui.SemanticsUpdateBuilder.updateNode]
  List<ui.StringAttribute>? get hintAttributes => _hintAttributes;
  List<ui.StringAttribute>? _hintAttributes;

  static const int _hintIndex = 1 << 11;

  /// Whether the [hint] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isHintDirty => _isDirty(_hintIndex);
  void _markHintDirty() {
    _dirtyFields |= _hintIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  String? get value => _value;
  String? _value;

  /// See [ui.SemanticsUpdateBuilder.updateNode]
  List<ui.StringAttribute>? get valueAttributes => _valueAttributes;
  List<ui.StringAttribute>? _valueAttributes;

  /// Whether this object contains a non-empty value.
  bool get hasValue => _value != null && _value!.isNotEmpty;

  static const int _valueIndex = 1 << 12;

  /// Whether the [value] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isValueDirty => _isDirty(_valueIndex);
  void _markValueDirty() {
    _dirtyFields |= _valueIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  String? get increasedValue => _increasedValue;
  String? _increasedValue;

  /// See [ui.SemanticsUpdateBuilder.updateNode]
  List<ui.StringAttribute>? get increasedValueAttributes => _increasedValueAttributes;
  List<ui.StringAttribute>? _increasedValueAttributes;

  static const int _increasedValueIndex = 1 << 13;

  /// Whether the [increasedValue] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isIncreasedValueDirty => _isDirty(_increasedValueIndex);
  void _markIncreasedValueDirty() {
    _dirtyFields |= _increasedValueIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  String? get decreasedValue => _decreasedValue;
  String? _decreasedValue;

  /// See [ui.SemanticsUpdateBuilder.updateNode]
  List<ui.StringAttribute>? get decreasedValueAttributes => _decreasedValueAttributes;
  List<ui.StringAttribute>? _decreasedValueAttributes;

  static const int _decreasedValueIndex = 1 << 14;

  /// Whether the [decreasedValue] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isDecreasedValueDirty => _isDirty(_decreasedValueIndex);
  void _markDecreasedValueDirty() {
    _dirtyFields |= _decreasedValueIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  ui.TextDirection? get textDirection => _textDirection;
  ui.TextDirection? _textDirection;

  static const int _textDirectionIndex = 1 << 15;

  /// Whether the [textDirection] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isTextDirectionDirty => _isDirty(_textDirectionIndex);
  void _markTextDirectionDirty() {
    _dirtyFields |= _textDirectionIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  Float32List? get transform => _transform;
  Float32List? _transform;

  static const int _transformIndex = 1 << 16;

  /// Whether the [transform] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isTransformDirty => _isDirty(_transformIndex);
  void _markTransformDirty() {
    _dirtyFields |= _transformIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  Int32List? get childrenInTraversalOrder => _childrenInTraversalOrder;
  Int32List? _childrenInTraversalOrder;

  static const int _childrenInTraversalOrderIndex = 1 << 19;

  /// Whether the [childrenInTraversalOrder] field has been updated but has not
  /// been applied to the DOM yet.
  bool get isChildrenInTraversalOrderDirty =>
      _isDirty(_childrenInTraversalOrderIndex);
  void _markChildrenInTraversalOrderDirty() {
    _dirtyFields |= _childrenInTraversalOrderIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  Int32List? get childrenInHitTestOrder => _childrenInHitTestOrder;
  Int32List? _childrenInHitTestOrder;

  static const int _childrenInHitTestOrderIndex = 1 << 20;

  /// Whether the [childrenInHitTestOrder] field has been updated but has not
  /// been applied to the DOM yet.
  bool get isChildrenInHitTestOrderDirty =>
      _isDirty(_childrenInHitTestOrderIndex);
  void _markChildrenInHitTestOrderDirty() {
    _dirtyFields |= _childrenInHitTestOrderIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  Int32List? get additionalActions => _additionalActions;
  Int32List? _additionalActions;

  static const int _additionalActionsIndex = 1 << 21;

  /// Whether the [additionalActions] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isAdditionalActionsDirty => _isDirty(_additionalActionsIndex);
  void _markAdditionalActionsDirty() {
    _dirtyFields |= _additionalActionsIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  String? get tooltip => _tooltip;
  String? _tooltip;

  /// Whether this object contains a non-empty tooltip.
  bool get hasTooltip => _tooltip != null && _tooltip!.isNotEmpty;

  static const int _tooltipIndex = 1 << 22;

  /// Whether the [tooltip] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isTooltipDirty => _isDirty(_tooltipIndex);
  void _markTooltipDirty() {
    _dirtyFields |= _tooltipIndex;
  }

  /// See [ui.SemanticsUpdateBuilder.updateNode].
  int get platformViewId => _platformViewId;
  int _platformViewId = -1;

  /// Whether this object represents a platform view.
  bool get isPlatformView => _platformViewId != -1;

  static const int _platformViewIdIndex = 1 << 23;

  /// Whether the [platformViewId] field has been updated but has not been
  /// applied to the DOM yet.
  bool get isPlatformViewIdDirty => _isDirty(_platformViewIdIndex);
  void _markPlatformViewIdDirty() {
    _dirtyFields |= _platformViewIdIndex;
  }

  /// A unique permanent identifier of the semantics node in the tree.
  final int id;

  /// Controls the semantics tree that this node participates in.
  final EngineSemanticsOwner owner;

  /// Bitfield showing which fields have been updated but have not yet been
  /// applied to the DOM.
  ///
  /// Instead of use this field directly, prefer using one of the "is*Dirty"
  /// getters, e.g. [isFlagsDirty].
  ///
  /// The bitfield supports up to 31 bits.
  int _dirtyFields = -1; // initial value is when all relevant bits are set

  /// Whether the field corresponding to the [fieldIndex] has been updated.
  bool _isDirty(int fieldIndex) => (_dirtyFields & fieldIndex) != 0;

  /// The dom element of this semantics object.
  DomElement get element => primaryRole!.element;

  /// Returns the HTML element that contains the HTML elements of direct
  /// children of this object.
  ///
  /// The element is created lazily. When the child list is empty this element
  /// is not created. This is necessary for "aria-label" to function correctly.
  /// The browser will ignore the [label] of HTML element that contain child
  /// elements.
  DomElement? getOrCreateChildContainer() {
    if (_childContainerElement == null) {
      _childContainerElement = createDomElement('flt-semantics-container');
      _childContainerElement!.style
        ..position = 'absolute'
        // Ignore pointer events on child container so that platform views
        // behind it can be reached.
        ..pointerEvents = 'none';
      element.append(_childContainerElement!);
    }
    return _childContainerElement;
  }

  /// The element that contains the elements belonging to the child semantics
  /// nodes.
  ///
  /// This element is used to correct for [_rect] offsets. It is only non-`null`
  /// when there are non-zero children (i.e. when [hasChildren] is `true`).
  DomElement? _childContainerElement;

  /// The parent of this semantics object.
  ///
  /// This value is not final until the tree is finalized. It is not safe to
  /// rely on this value in the middle of a semantics tree update. It is safe to
  /// use this value in post-update callback (see [SemanticsUpdatePhase] and
  /// [EngineSemanticsOwner.addOneTimePostUpdateCallback]).
  SemanticsObject? get parent {
    assert(owner.phase == SemanticsUpdatePhase.postUpdate);
    return _parent;
  }
  SemanticsObject? _parent;

  /// Whether this node currently has a given [SemanticsFlag].
  bool hasFlag(ui.SemanticsFlag flag) => _flags & flag.index != 0;

  /// Whether [actions] contains the given action.
  bool hasAction(ui.SemanticsAction action) => (_actions! & action.index) != 0;

  /// Whether this object represents a widget that can receive input focus.
  bool get isFocusable => hasFlag(ui.SemanticsFlag.isFocusable);

  /// Whether this object currently has input focus.
  ///
  /// This value only makes sense if [isFocusable] is true.
  bool get hasFocus => hasFlag(ui.SemanticsFlag.isFocused);

  /// Whether this object can be in one of "enabled" or "disabled" state.
  ///
  /// If this is true, [isEnabled] communicates the state.
  bool get hasEnabledState => hasFlag(ui.SemanticsFlag.hasEnabledState);

  /// Whether this object is enabled.
  ///
  /// This field is only meaningful if [hasEnabledState] is true.
  bool get isEnabled => hasFlag(ui.SemanticsFlag.isEnabled);

  /// Whether this object represents a vertically scrollable area.
  bool get isVerticalScrollContainer =>
      hasAction(ui.SemanticsAction.scrollDown) ||
      hasAction(ui.SemanticsAction.scrollUp);

  /// Whether this object represents a horizontally scrollable area.
  bool get isHorizontalScrollContainer =>
      hasAction(ui.SemanticsAction.scrollLeft) ||
      hasAction(ui.SemanticsAction.scrollRight);

  /// Whether this object represents a scrollable area in any direction.
  bool get isScrollContainer => isVerticalScrollContainer || isHorizontalScrollContainer;

  /// Whether this object has a non-empty list of children.
  bool get hasChildren =>
      _childrenInTraversalOrder != null && _childrenInTraversalOrder!.isNotEmpty;

  /// Whether this object represents an editable text field.
  bool get isTextField => hasFlag(ui.SemanticsFlag.isTextField);

    /// Whether this object represents an editable text field.
  bool get isLink => hasFlag(ui.SemanticsFlag.isLink);

  /// Whether this object needs screen readers attention right away.
  bool get isLiveRegion =>
      hasFlag(ui.SemanticsFlag.isLiveRegion) &&
      !hasFlag(ui.SemanticsFlag.isHidden);

  /// Whether this object represents an image with no tappable functionality.
  bool get isVisualOnly =>
      hasFlag(ui.SemanticsFlag.isImage) &&
      !isTappable &&
      !isButton;

  /// Whether this node defines a scope for a route.
  ///
  /// See also [Role.dialog].
  bool get scopesRoute => hasFlag(ui.SemanticsFlag.scopesRoute);

  /// Whether this node describes a route.
  ///
  /// See also [Role.dialog].
  bool get namesRoute => hasFlag(ui.SemanticsFlag.namesRoute);

  /// Whether this object carry enabled/disabled state (and if so whether it is
  /// enabled).
  ///
  /// See [EnabledState] for more details.
  EnabledState enabledState() {
    if (hasFlag(ui.SemanticsFlag.hasEnabledState)) {
      if (hasFlag(ui.SemanticsFlag.isEnabled)) {
        return EnabledState.enabled;
      } else {
        return EnabledState.disabled;
      }
    } else {
      return EnabledState.noOpinion;
    }
  }

  /// Updates this object from data received from a semantics [update].
  ///
  /// Does not update children. Children are updated in a separate pass because
  /// at this point children's self information is not ready yet.
  void updateSelf(SemanticsNodeUpdate update) {
    // Update all field values and their corresponding dirty flags before
    // applying the updates to the DOM.
    if (_flags != update.flags) {
      _flags = update.flags;
      _markFlagsDirty();
    }

    if (_value != update.value) {
      _value = update.value;
      _markValueDirty();
    }

    if (_valueAttributes != update.valueAttributes) {
      _valueAttributes = update.valueAttributes;
      _markValueDirty();
    }

    if (_label != update.label) {
      _label = update.label;
      _markLabelDirty();
    }

    if (_labelAttributes != update.labelAttributes) {
      _labelAttributes = update.labelAttributes;
      _markLabelDirty();
    }

    if (_rect != update.rect) {
      _rect = update.rect;
      _markRectDirty();
    }

    if (_transform != update.transform) {
      _transform = update.transform;
      _markTransformDirty();
    }

    if (_scrollPosition != update.scrollPosition) {
      _scrollPosition = update.scrollPosition;
      _markScrollPositionDirty();
    }

    if (_actions != update.actions) {
      _actions = update.actions;
      _markActionsDirty();
    }

    if (_textSelectionBase != update.textSelectionBase) {
      _textSelectionBase = update.textSelectionBase;
      _markTextSelectionBaseDirty();
    }

    if (_textSelectionExtent != update.textSelectionExtent) {
      _textSelectionExtent = update.textSelectionExtent;
      _markTextSelectionExtentDirty();
    }

    if (_scrollChildren != update.scrollChildren) {
      _scrollChildren = update.scrollChildren;
      _markScrollChildrenDirty();
    }

    if (_scrollIndex != update.scrollIndex) {
      _scrollIndex = update.scrollIndex;
      _markScrollIndexDirty();
    }

    if (_scrollExtentMax != update.scrollExtentMax) {
      _scrollExtentMax = update.scrollExtentMax;
      _markScrollExtentMaxDirty();
    }

    if (_scrollExtentMin != update.scrollExtentMin) {
      _scrollExtentMin = update.scrollExtentMin;
      _markScrollExtentMinDirty();
    }

    if (_hint != update.hint) {
      _hint = update.hint;
      _markHintDirty();
    }

    if (_hintAttributes != update.hintAttributes) {
      _hintAttributes = update.hintAttributes;
      _markHintDirty();
    }

    if (_increasedValue != update.increasedValue) {
      _increasedValue = update.increasedValue;
      _markIncreasedValueDirty();
    }

    if (_increasedValueAttributes != update.increasedValueAttributes) {
      _increasedValueAttributes = update.increasedValueAttributes;
      _markIncreasedValueDirty();
    }

    if (_decreasedValue != update.decreasedValue) {
      _decreasedValue = update.decreasedValue;
      _markDecreasedValueDirty();
    }

    if (_decreasedValueAttributes != update.decreasedValueAttributes) {
      _decreasedValueAttributes = update.decreasedValueAttributes;
      _markDecreasedValueDirty();
    }

    if (_tooltip != update.tooltip) {
      _tooltip = update.tooltip;
      _markTooltipDirty();
    }

    if (_textDirection != update.textDirection) {
      _textDirection = update.textDirection;
      _markTextDirectionDirty();
    }

    if (_childrenInHitTestOrder != update.childrenInHitTestOrder) {
      _childrenInHitTestOrder = update.childrenInHitTestOrder;
      _markChildrenInHitTestOrderDirty();
    }

    if (_childrenInTraversalOrder != update.childrenInTraversalOrder) {
      _childrenInTraversalOrder = update.childrenInTraversalOrder;
      _markChildrenInTraversalOrderDirty();
    }

    if (_additionalActions != update.additionalActions) {
      _additionalActions = update.additionalActions;
      _markAdditionalActionsDirty();
    }

    if (_platformViewId != update.platformViewId) {
      _platformViewId = update.platformViewId;
      _markPlatformViewIdDirty();
    }

    // Apply updates to the DOM.
    _updateRoles();

    // All properties that affect positioning and sizing are checked together
    // any one of them triggers position and size recomputation.
    if (isRectDirty || isTransformDirty || isScrollPositionDirty) {
      recomputePositionAndSize();
    }

    // Ignore pointer events on all container nodes and all platform view nodes.
    // This is so that the platform views are not obscured by semantic elements
    // and can be reached by inspecting the web page.
    if (!hasChildren && !isPlatformView) {
      element.style.pointerEvents = 'all';
    } else {
      element.style.pointerEvents = 'none';
    }
  }

  /// The order children are currently rendered in.
  List<SemanticsObject>? _currentChildrenInRenderOrder;

  /// Updates direct children of this node, if any.
  ///
  /// Specifies two orders of direct children:
  ///
  /// * Traversal order: the logical order of child nodes that establishes the
  ///   next and previous relationship between UI widgets. When the user
  ///   traverses the UI using next/previous gestures the accessibility focus
  ///   follows the traversal order.
  /// * Hit-test order: determines the top/bottom relationship between widgets.
  ///   When the user is inspecting the UI using the drag gesture, the widgets
  ///   that appear "on top" hit-test order wise take the focus. This order is
  ///   communicated in the DOM using the inverse paint order, specified by the
  ///   z-index CSS style attribute.
  void updateChildren() {
    // Trivial case: remove all children.
    if (_childrenInHitTestOrder == null ||
        _childrenInHitTestOrder!.isEmpty) {
      if (_currentChildrenInRenderOrder == null ||
          _currentChildrenInRenderOrder!.isEmpty) {
        // A container element must not have been created when child list is empty.
        assert(_childContainerElement == null);
        _currentChildrenInRenderOrder = null;
        return;
      }

      // A container element must have been created when child list is not empty.
      assert(_childContainerElement != null);

      // Remove all children from this semantics object.
      final int len = _currentChildrenInRenderOrder!.length;
      for (int i = 0; i < len; i++) {
        owner._detachObject(_currentChildrenInRenderOrder![i].id);
      }
      _childContainerElement!.remove();
      _childContainerElement = null;
      _currentChildrenInRenderOrder = null;
      return;
    }

    // At this point it is guaranteed to have at least one child.
    final Int32List childrenInTraversalOrder = _childrenInTraversalOrder!;
    final Int32List childrenInHitTestOrder = _childrenInHitTestOrder!;
    final int childCount = childrenInHitTestOrder.length;
    final DomElement? containerElement = getOrCreateChildContainer();

    assert(childrenInTraversalOrder.length == childrenInHitTestOrder.length);

    // Always render in traversal order, because the accessibility traversal
    // is determined by the DOM order of elements.
    final List<SemanticsObject> childrenInRenderOrder = <SemanticsObject>[];
    for (int i = 0; i < childCount; i++) {
      childrenInRenderOrder.add(owner._semanticsTree[childrenInTraversalOrder[i]]!);
    }

    // The z-index determines hit testing. Technically, it also affects paint
    // order. However, this does not matter because our ARIA tree is invisible.
    // On top of that, it is a bad UI practice when hit test order does not match
    // paint order, because human eye must be able to predict hit test order
    // simply by looking at the UI (if a dialog is painted on top of a dismiss
    // barrier, then tapping on anything inside the dialog should not land on
    // the barrier).
    final bool zIndexMatters = childCount > 1;
    if (zIndexMatters) {
      for (int i = 0; i < childCount; i++) {
        final SemanticsObject child = owner._semanticsTree[childrenInHitTestOrder[i]]!;

        // Invert the z-index because hit-test order is inverted with respect to
        // paint order.
        child.element.style.zIndex = '${childCount - i}';
      }
    }

    // Trivial case: previous list was empty => just populate the container.
    if (_currentChildrenInRenderOrder == null ||
        _currentChildrenInRenderOrder!.isEmpty) {
      for (final SemanticsObject child in childrenInRenderOrder) {
        containerElement!.append(child.element);
        owner._attachObject(parent: this, child: child);
      }
      _currentChildrenInRenderOrder = childrenInRenderOrder;
      return;
    }

    // At this point it is guaranteed to have had a non-empty previous child list.
    final List<SemanticsObject> previousChildrenInRenderOrder = _currentChildrenInRenderOrder!;
    final int previousCount = previousChildrenInRenderOrder.length;

    // Both non-empty case.

    // Problem: child nodes have been added, removed, and/or reordered. On the
    //          web, many assistive technologies cannot track DOM elements
    //          moving around, losing focus. The best approach is to try to keep
    //          child elements as stable as possible.
    // Solution: find all common elements in both lists and record their indices
    //           in the old list (in the `intersectionIndicesOld` variable). The
    //           longest increases subsequence provides the longest chain of
    //           semantics nodes that didn't move relative to each other. Those
    //           nodes (represented by the `stationaryIds` variable) are kept
    //           stationary, while all others are moved/inserted/deleted around
    //           them. This gives the maximum node stability, and covers most
    //           use-cases, including scrolling in any direction, insertions,
    //           deletions, drag'n'drop, etc.

    // Indices into the old child list pointing at children that also exist in
    // the new child list.
    final List<int> intersectionIndicesOld = <int>[];

    int newIndex = 0;

    // The smallest of the two child list lengths.
    final int minLength = math.min(previousCount, childCount);

    // Scan forward until first discrepancy.
    while (newIndex < minLength &&
        previousChildrenInRenderOrder[newIndex] ==
            childrenInRenderOrder[newIndex]) {
      intersectionIndicesOld.add(newIndex);
      newIndex += 1;
    }

    // Trivial case: child lists are identical both in length and order => do nothing.
    if (previousCount == childrenInRenderOrder.length && newIndex == childCount) {
      return;
    }

    // If child lists are not identical, continue computing the intersection
    // between the two lists.
    while (newIndex < childCount) {
      for (int oldIndex = 0; oldIndex < previousCount; oldIndex += 1) {
        if (previousChildrenInRenderOrder[oldIndex] ==
            childrenInRenderOrder[newIndex]) {
          intersectionIndicesOld.add(oldIndex);
          break;
        }
      }
      newIndex += 1;
    }

    // The longest sub-sequence in the old list maximizes the number of children
    // that do not need to be moved.
    final List<int?> longestSequence = longestIncreasingSubsequence(intersectionIndicesOld);
    final List<int> stationaryIds = <int>[];
    for (int i = 0; i < longestSequence.length; i += 1) {
      stationaryIds.add(
        previousChildrenInRenderOrder[intersectionIndicesOld[longestSequence[i]!]].id
      );
    }

    // Remove children that are no longer in the list.
    for (int i = 0; i < previousCount; i++) {
      if (!intersectionIndicesOld.contains(i)) {
        // Child not in the intersection. Must be removed.
        final int childId = previousChildrenInRenderOrder[i].id;
        owner._detachObject(childId);
      }
    }

    DomElement? refNode;
    for (int i = childCount - 1; i >= 0; i -= 1) {
      final SemanticsObject child = childrenInRenderOrder[i];
      if (!stationaryIds.contains(child.id)) {
        if (refNode == null) {
          containerElement!.append(child.element);
        } else {
          containerElement!.insertBefore(child.element, refNode);
        }
        owner._attachObject(parent: this, child: child);
      } else {
        assert(child._parent == this);
      }
      refNode = child.element;
    }

    _currentChildrenInRenderOrder = childrenInRenderOrder;
  }

  /// The primary role of this node.
  ///
  /// The primary role is assigned by [updateSelf] based on the combination of
  /// semantics flags and actions.
  PrimaryRoleManager? primaryRole;

  PrimaryRole _getPrimaryRoleIdentifier() {
    // The most specific role should take precedence.
    if (isPlatformView) {
      return PrimaryRole.platformView;
    } else if (isTextField) {
      return PrimaryRole.textField;
    } else if (isIncrementable) {
      return PrimaryRole.incrementable;
    } else if (isVisualOnly) {
      return PrimaryRole.image;
    } else if (isCheckable) {
      return PrimaryRole.checkable;
    } else if (isButton) {
      return PrimaryRole.button;
    } else if (isScrollContainer) {
      return PrimaryRole.scrollable;
    } else if (scopesRoute) {
      return PrimaryRole.dialog;
    } else if (isLink) {
      return PrimaryRole.link;
    } else {
      return PrimaryRole.generic;
    }
  }

  PrimaryRoleManager _createPrimaryRole(PrimaryRole role) {
    return switch (role) {
      PrimaryRole.textField => TextField(this),
      PrimaryRole.scrollable => Scrollable(this),
      PrimaryRole.incrementable => Incrementable(this),
      PrimaryRole.button => Button(this),
      PrimaryRole.checkable => Checkable(this),
      PrimaryRole.dialog => Dialog(this),
      PrimaryRole.image => ImageRoleManager(this),
      PrimaryRole.platformView => PlatformViewRoleManager(this),
      PrimaryRole.link => Link(this),
      PrimaryRole.generic => GenericRole(this),
    };
  }

  /// Detects the roles that this semantics object corresponds to and asks the
  /// respective role managers to update the DOM.
  void _updateRoles() {
    PrimaryRoleManager? currentPrimaryRole = primaryRole;
    final PrimaryRole roleId = _getPrimaryRoleIdentifier();
    final DomElement? previousElement = primaryRole?.element;

    if (currentPrimaryRole != null) {
      if (currentPrimaryRole.role == roleId) {
        // Already has a primary role assigned and the role is the same as before,
        // so simply perform an update.
        currentPrimaryRole.update();
        return;
      } else {
        // Role changed. This should be avoided as much as possible, but the
        // web engine will attempt a best with the switch by cleaning old ARIA
        // role data and start anew.
        currentPrimaryRole.dispose();
        currentPrimaryRole = null;
        primaryRole = null;
      }
    }

    // This handles two cases:
    //  * The node was just created and needs a primary role manager.
    //  * (Uncommon) the node changed its primary role, its previous primary
    //    role manager was disposed of, and now it needs a new one.
    if (currentPrimaryRole == null) {
      currentPrimaryRole = _createPrimaryRole(roleId);
      primaryRole = currentPrimaryRole;
      currentPrimaryRole.update();
    }

    // Reparent element.
    if (previousElement != element) {
      final DomElement? container = _childContainerElement;
      if (container != null) {
        element.append(container);
      }
      final DomElement? parent = previousElement?.parent;
      if (parent != null) {
        parent.insertBefore(element, previousElement);
        previousElement!.remove();
      }
    }
  }

  /// Whether the object represents an UI element with "increase" or "decrease"
  /// controls, e.g. a slider.
  ///
  /// Such objects are expressed in HTML using `<input type="range">`.
  bool get isIncrementable =>
      hasAction(ui.SemanticsAction.increase) ||
      hasAction(ui.SemanticsAction.decrease);

  /// Whether the object represents a button.
  bool get isButton => hasFlag(ui.SemanticsFlag.isButton);

  /// Represents a tappable or clickable widget, such as button, icon button,
  /// "hamburger" menu, etc.
  bool get isTappable => hasAction(ui.SemanticsAction.tap);

  bool get isCheckable =>
      hasFlag(ui.SemanticsFlag.hasCheckedState) ||
      hasFlag(ui.SemanticsFlag.hasToggledState);

  /// Role-specific adjustment of the vertical position of the child container.
  ///
  /// This is used, for example, by the [Scrollable] to compensate for the
  /// `scrollTop` offset in the DOM.
  ///
  /// This field must not be null.
  double verticalContainerAdjustment = 0.0;

  /// Role-specific adjustment of the horizontal position of the child
  /// container.
  ///
  /// This is used, for example, by the [Scrollable] to compensate for the
  /// `scrollLeft` offset in the DOM.
  ///
  /// This field must not be null.
  double horizontalContainerAdjustment = 0.0;

  /// Computes the size and position of [element] and, if this element
  /// [hasChildren], of [getOrCreateChildContainer].
  void recomputePositionAndSize() {
    element.style
      ..width = '${_rect!.width}px'
      ..height = '${_rect!.height}px';

    final DomElement? containerElement =
        hasChildren ? getOrCreateChildContainer() : null;

    final bool hasZeroRectOffset = _rect!.top == 0.0 && _rect!.left == 0.0;
    final Float32List? transform = _transform;
    final bool hasIdentityTransform =
        transform == null || isIdentityFloat32ListTransform(transform);

    if (hasZeroRectOffset &&
        hasIdentityTransform &&
        verticalContainerAdjustment == 0.0 &&
        horizontalContainerAdjustment == 0.0) {
      _clearSemanticElementTransform(element);
      if (containerElement != null) {
        _clearSemanticElementTransform(containerElement);
      }
      return;
    }

    late Matrix4 effectiveTransform;
    bool effectiveTransformIsIdentity = true;
    if (!hasZeroRectOffset) {
      if (transform == null) {
        final double left = _rect!.left;
        final double top = _rect!.top;
        effectiveTransform = Matrix4.translationValues(left, top, 0.0);
        effectiveTransformIsIdentity = left == 0.0 && top == 0.0;
      } else {
        // Clone to avoid mutating _transform.
        effectiveTransform = Matrix4.fromFloat32List(transform).clone()
          ..translate(_rect!.left, _rect!.top);
        effectiveTransformIsIdentity = effectiveTransform.isIdentity();
      }
    } else if (!hasIdentityTransform) {
      effectiveTransform = Matrix4.fromFloat32List(transform);
      effectiveTransformIsIdentity = false;
    }

    if (!effectiveTransformIsIdentity) {
      element.style
        ..transformOrigin = '0 0 0'
        ..transform = matrix4ToCssTransform(effectiveTransform);
    } else {
      _clearSemanticElementTransform(element);
    }

    if (containerElement != null) {
      if (!hasZeroRectOffset ||
          verticalContainerAdjustment != 0.0 ||
          horizontalContainerAdjustment != 0.0) {
        final double translateX = -_rect!.left + horizontalContainerAdjustment;
        final double translateY = -_rect!.top + verticalContainerAdjustment;
        containerElement.style
          ..top = '${translateY}px'
          ..left = '${translateX}px';
      } else {
        _clearSemanticElementTransform(containerElement);
      }
    }
  }

  /// Clears the transform on a semantic element as if an identity transform is
  /// applied.
  ///
  /// On macOS and iOS, VoiceOver requires `left=0; top=0` value to correctly
  /// handle traversal order.
  ///
  /// See https://github.com/flutter/flutter/issues/73347.
  static void _clearSemanticElementTransform(DomElement element) {
    element.style
      ..removeProperty('transform-origin')
      ..removeProperty('transform');
    if (isMacOrIOS) {
      element.style
        ..top = '0px'
        ..left = '0px';
    } else {
      element.style
        ..removeProperty('top')
        ..removeProperty('left');
    }
  }

  /// Recursively visits the tree rooted at `this` node in depth-first fashion
  /// in the order nodes were rendered into the DOM.
  ///
  /// Useful for debugging only.
  ///
  /// Calls the [callback] for `this` node, then for all of its descendants.
  ///
  /// Unlike [visitDepthFirstInTraversalOrder] this method can traverse
  /// partially updated, incomplete, or inconsistent tree.
  void _debugVisitRenderedSemanticNodesDepthFirst(void Function(SemanticsObject) callback) {
    callback(this);
    _currentChildrenInRenderOrder?.forEach((SemanticsObject child) {
      child._debugVisitRenderedSemanticNodesDepthFirst(callback);
    });
  }

  /// Recursively visits the tree rooted at `this` node in depth-first fashion
  /// in traversal order.
  ///
  /// Calls the [callback] for `this` node, then for all of its descendants. If
  /// the callback returns true, continues visiting descendants. Otherwise,
  /// stops immediately after visiting the node that caused the callback to
  /// return false.
  void visitDepthFirstInTraversalOrder(bool Function(SemanticsObject) callback) {
    _visitDepthFirstInTraversalOrder(callback);
  }

  bool _visitDepthFirstInTraversalOrder(bool Function(SemanticsObject) callback) {
    final bool shouldContinueVisiting = callback(this);

    if (!shouldContinueVisiting) {
      return false;
    }

    final Int32List? childrenInTraversalOrder = _childrenInTraversalOrder;

    if (childrenInTraversalOrder == null) {
      return true;
    }

    for (final int childId in childrenInTraversalOrder) {
      final SemanticsObject? child = owner._semanticsTree[childId];

      assert(
        child != null,
        'visitDepthFirstInTraversalOrder must only be called after the node '
        'tree has been established. However, child #$childId does not have its '
        'SemanticsNode created at the time this method was called.',
      );

      if (!child!._visitDepthFirstInTraversalOrder(callback)) {
        return false;
      }
    }

    return true;
  }

  @override
  String toString() {
    String result = super.toString();
    assert(() {
      final String children = _childrenInTraversalOrder != null &&
              _childrenInTraversalOrder!.isNotEmpty
          ? '[${_childrenInTraversalOrder!.join(', ')}]'
          : '<empty>';
      result = '$runtimeType(#$id, children: $children)';
      return true;
    }());
    return result;
  }

  bool _isDisposed = false;

  void dispose() {
    assert(!_isDisposed);
    _isDisposed = true;
    element.remove();
    _parent = null;
    primaryRole?.dispose();
    primaryRole = null;
  }
}

/// Controls how pointer events and browser-detected gestures are treated by
/// the Web Engine.
enum AccessibilityMode {
  /// Flutter is not told whether the assistive technology is enabled or not.
  ///
  /// This is the default mode.
  ///
  /// In this mode a gesture recognition system is used that deduplicates
  /// gestures detected by Flutter with gestures detected by the browser.
  unknown,

  /// Flutter is told whether the assistive technology is enabled.
  known,
}

/// Called when the current [GestureMode] changes.
typedef GestureModeCallback = void Function(GestureMode mode);

/// The method used to detect user gestures.
enum GestureMode {
  /// Send pointer events to Flutter to detect gestures using framework-level
  /// gesture recognizers and gesture arenas.
  pointerEvents,

  /// Listen to browser-detected gestures and report them to the framework as
  /// [ui.SemanticsAction].
  browserGestures,
}

/// The current phase of the semantic update.
enum SemanticsUpdatePhase {
  /// No update is in progress.
  ///
  /// When the semantics owner receives an update, it enters the [updating]
  /// phase from the idle phase.
  idle,

  /// Updating individual [SemanticsObject] nodes by calling
  /// [RoleManager.update] and fixing parent-child relationships.
  ///
  /// After this phase is done, the owner enters the [postUpdate] phase.
  updating,

  /// Post-update callbacks are being called.
  ///
  /// At this point all nodes have been updated, the parent child hierarchy has
  /// been established, the DOM tree is in sync with the semantics tree, and
  /// [RoleManager.dispose] has been called on removed nodes.
  ///
  /// After this phase is done, the owner switches back to [idle].
  postUpdate,
}

/// The semantics system of the Web Engine.
///
/// Maintains global properties and behaviors of semantics in the engine, such
/// as whether semantics is currently enabled or disabled.
class EngineSemantics {
  EngineSemantics._();

  /// The singleton instance that manages semantics.
  static EngineSemantics get instance {
    return _instance ??= EngineSemantics._();
  }

  static EngineSemantics? _instance;

  /// The tag name for the accessibility announcements host.
  static const String announcementsHostTagName = 'flt-announcement-host';

  /// Implements verbal accessibility announcements.
  final AccessibilityAnnouncements accessibilityAnnouncements =
      AccessibilityAnnouncements(hostElement: _initializeAccessibilityAnnouncementHost());

  static DomElement _initializeAccessibilityAnnouncementHost() {
    final DomElement host = createDomElement(announcementsHostTagName);
    domDocument.body!.append(host);
    return host;
  }

  /// Disables semantics and uninitializes the singleton [instance].
  ///
  /// Instances of [EngineSemanticsOwner] are no longer valid after calling this
  /// method. Using them will lead to undefined behavior. This method is only
  /// meant to be used for testing.
  static void debugResetSemantics() {
    if (_instance == null) {
      return;
    }
    _instance!.semanticsEnabled = false;
    _instance = null;
  }

  /// Whether the user has requested that [updateSemantics] be called when the
  /// semantic contents of window changes.
  ///
  /// The [ui.PlatformDispatcher.onSemanticsEnabledChanged] callback is called
  /// whenever this value changes.
  ///
  /// This is separate from accessibility [mode], which controls how gestures
  /// are interpreted when this value is true.
  bool get semanticsEnabled => _semanticsEnabled;
  bool _semanticsEnabled = false;
  set semanticsEnabled(bool value) {
    if (value == _semanticsEnabled) {
      return;
    }
    final EngineAccessibilityFeatures original =
        EnginePlatformDispatcher.instance.configuration.accessibilityFeatures
        as EngineAccessibilityFeatures;
    final PlatformConfiguration newConfiguration =
        EnginePlatformDispatcher.instance.configuration.copyWith(
            accessibilityFeatures:
                original.copyWith(accessibleNavigation: value));
    EnginePlatformDispatcher.instance.configuration = newConfiguration;

    _semanticsEnabled = value;

    if (!_semanticsEnabled) {
      // Do not process browser events at all when semantics is explicitly
      // disabled. All gestures are handled by the framework-level gesture
      // recognizers from pointer events.
      if (_gestureMode != GestureMode.pointerEvents) {
        _gestureMode = GestureMode.pointerEvents;
        _notifyGestureModeListeners();
      }
      for (final EngineFlutterView view in EnginePlatformDispatcher.instance.views) {
        view.semantics.reset();
      }
      _gestureModeClock?.datetime = null;
    }
    EnginePlatformDispatcher.instance.updateSemanticsEnabled(_semanticsEnabled);
  }

  /// Prepares the semantics system for a semantic tree update.
  ///
  /// This method must be called prior to updating the semantics inside any
  /// individual view.
  ///
  /// Automatically enables semantics in a production setting. In Flutter test
  /// environment keeps engine semantics turned off due to tests frequently
  /// sending inconsistent semantics updates.
  ///
  /// The caller is expected to check if [semanticsEnabled] is true prior to
  /// actually updating the semantic DOM.
  void didReceiveSemanticsUpdate() {
    if (!_semanticsEnabled) {
      if (ui_web.debugEmulateFlutterTesterEnvironment) {
        // Running Flutter widget tests in a fake environment. Don't enable
        // engine semantics. Test semantics trees violate invariants in ways
        // production implementation isn't built to handle. For example, tests
        // routinely reset semantics node IDs, which is messing up the update
        // process.
        return;
      } else {
        // Running a real app. Auto-enable engine semantics.
        semanticsHelper.dispose(); // placeholder no longer needed
        semanticsEnabled = true;
      }
    }
  }

  TimestampFunction _now = () => DateTime.now();

  void debugOverrideTimestampFunction(TimestampFunction value) {
    _now = value;
  }

  void debugResetTimestampFunction() {
    _now = () => DateTime.now();
  }

  final SemanticsHelper semanticsHelper = SemanticsHelper();

  /// Controls how pointer events and browser-detected gestures are treated by
  /// the Web Engine.
  ///
  /// The default mode is [AccessibilityMode.unknown].
  AccessibilityMode mode = AccessibilityMode.unknown;

  /// Currently used [GestureMode].
  ///
  /// This value changes automatically depending on the incoming input events.
  /// Functionality that implements different strategies depending on this mode
  /// would use [addGestureModeListener] and [removeGestureModeListener] to get
  /// notifications about when the value of this field changes.
  GestureMode get gestureMode => _gestureMode;
  GestureMode _gestureMode = GestureMode.browserGestures;

  AlarmClock? _gestureModeClock;

  AlarmClock? _getGestureModeClock() {
    if (_gestureModeClock == null) {
      _gestureModeClock = AlarmClock(_now);
      _gestureModeClock!.callback = () {
        if (_gestureMode == GestureMode.browserGestures) {
          return;
        }

        _gestureMode = GestureMode.browserGestures;
        _notifyGestureModeListeners();
      };
    }
    return _gestureModeClock;
  }

  /// Disables browser gestures temporarily because pointer events were detected.
  ///
  /// This is used to deduplicate gestures detected by Flutter and gestures
  /// detected by the browser. Flutter-detected gestures have higher precedence.
  void _temporarilyDisableBrowserGestureMode() {
    const Duration kDebounceThreshold = Duration(milliseconds: 500);
    _getGestureModeClock()!.datetime = _now().add(kDebounceThreshold);
    if (_gestureMode != GestureMode.pointerEvents) {
      _gestureMode = GestureMode.pointerEvents;
      _notifyGestureModeListeners();
    }
  }

  /// Receives DOM events from the pointer event system to correlate with the
  /// semantics events.
  ///
  /// Returns true if the event should be forwarded to the framework.
  ///
  /// The browser sends us both raw pointer events and gestures from
  /// [SemanticsObject.element]s. There could be three possibilities:
  ///
  /// 1. Assistive technology is enabled and Flutter knows that it is.
  /// 2. Assistive technology is disabled and Flutter knows that it isn't.
  /// 3. Flutter does not know whether an assistive technology is enabled.
  ///
  /// If [autoEnableOnTap] was called, this will automatically enable semantics
  /// if the user requests it.
  ///
  /// In the first case ignore raw pointer events and only interpret
  /// high-level gestures, e.g. "click".
  ///
  /// In the second case ignore high-level gestures and interpret the raw
  /// pointer events directly.
  ///
  /// Finally, in a mode when Flutter does not know if an assistive technology
  /// is enabled or not do a best-effort estimate which to respond to, raw
  /// pointer or high-level gestures. Avoid doing both because that will
  /// result in double-firing of event listeners, such as `onTap` on a button.
  /// The approach is to measure the distance between the last pointer
  /// event and a gesture event. If a gesture is receive "soon" after the last
  /// received pointer event (determined by a heuristic), it is debounced as it
  /// is likely that the gesture detected from the pointer even will do the
  /// right thing. However, if a standalone gesture is received, map it onto a
  /// [ui.SemanticsAction] to be processed by the framework.
  bool receiveGlobalEvent(DomEvent event) {
    // For pointer event reference see:
    //
    // https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events
    const List<String> pointerEventTypes = <String>[
      'pointerdown',
      'pointermove',
      'pointerleave',
      'pointerup',
      'pointercancel',
      'touchstart',
      'touchend',
      'touchmove',
      'touchcancel',
      'mousedown',
      'mousemove',
      'mouseleave',
      'mouseup',
      'keyup',
      'keydown',
    ];

    if (pointerEventTypes.contains(event.type)) {
      _temporarilyDisableBrowserGestureMode();
    }

    return semanticsHelper.shouldEnableSemantics(event);
  }

  /// Callbacks called when the [GestureMode] changes.
  ///
  /// Callbacks are called synchronously. HTML DOM updates made in a callback
  /// take effect in the current animation frame and/or the current message loop
  /// event.
  final List<GestureModeCallback> _gestureModeListeners = <GestureModeCallback>[];

  /// Calls the [callback] every time the current [GestureMode] changes.
  ///
  /// The callback is called synchronously. HTML DOM updates made in the
  /// callback take effect in the current animation frame and/or the current
  /// message loop event.
  void addGestureModeListener(GestureModeCallback callback) {
    _gestureModeListeners.add(callback);
  }

  /// Stops calling the [callback] when the [GestureMode] changes.
  ///
  /// The passed [callback] must be the exact same object as the one passed to
  /// [addGestureModeListener].
  void removeGestureModeListener(GestureModeCallback callback) {
    assert(_gestureModeListeners.contains(callback));
    _gestureModeListeners.remove(callback);
  }

  void _notifyGestureModeListeners() {
    for (int i = 0; i < _gestureModeListeners.length; i++) {
      _gestureModeListeners[i](_gestureMode);
    }
  }

  /// Whether a gesture event of type [eventType] should be accepted as a
  /// semantic action.
  ///
  /// If [mode] is [AccessibilityMode.known] the gesture is always accepted if
  /// [semanticsEnabled] is `true`, and it is always rejected if
  /// [semanticsEnabled] is `false`.
  ///
  /// If [mode] is [AccessibilityMode.unknown] the gesture is accepted if it is
  /// not accompanied by pointer events. In the presence of pointer events,
  /// delegate to Flutter's gesture detection system to produce gestures.
  bool shouldAcceptBrowserGesture(String eventType) {
    if (mode == AccessibilityMode.known) {
      // Do not ignore accessibility gestures in known mode, unless semantics
      // is explicitly disabled.
      return semanticsEnabled;
    }

    const List<String> pointerDebouncedGestures = <String>[
      'click',
      'scroll',
    ];

    if (pointerDebouncedGestures.contains(eventType)) {
      return _gestureMode == GestureMode.browserGestures;
    }

    return false;
  }
}

/// The top-level service that manages everything semantics-related.
class EngineSemanticsOwner {
  EngineSemanticsOwner(this.semanticsHost) {
    registerHotRestartListener(() {
      _rootSemanticsElement?.remove();
    });
  }

  /// The permanent element in the view's DOM structure that hosts the semantics
  /// tree.
  ///
  /// The only child of this element is the [rootSemanticsElement]. Unlike the
  /// root element, this element is never replaced. It is always part of the
  /// DOM structure of the respective [FlutterView].
  // TODO(yjbanov): rename to hostElement
  final DomElement semanticsHost;

  /// The DOM element corresponding to the root semantics node in the semantics
  /// tree.
  ///
  /// This element is the direct child of the [semanticsHost] and it is
  /// replaceable.
  // TODO(yjbanov): rename to rootElement
  DomElement? get rootSemanticsElement => _rootSemanticsElement;
  DomElement? _rootSemanticsElement;

  /// The current update phase of this semantics owner.
  SemanticsUpdatePhase get phase => _phase;
  SemanticsUpdatePhase _phase = SemanticsUpdatePhase.idle;

  final Map<int, SemanticsObject> _semanticsTree = <int, SemanticsObject>{};

  /// Map [SemanticsObject.id] to parent [SemanticsObject] it was attached to
  /// this frame.
  Map<int, SemanticsObject> _attachments = <int, SemanticsObject>{};

  /// Declares that the [child] must be attached to the [parent].
  ///
  /// Attachments take precedence over detachments (see [_detachObject]). This
  /// allows the same node to be detached from one parent in the tree and
  /// reattached to another parent.
  void _attachObject({required SemanticsObject parent, required SemanticsObject child}) {
    child._parent = parent;
    _attachments[child.id] = parent;
  }

  /// List of objects that were detached this frame.
  ///
  /// The objects in this list will be detached permanently unless they are
  /// reattached via the [_attachObject] method.
  List<SemanticsObject> _detachments = <SemanticsObject>[];

  /// Declares that the [SemanticsObject] with the given [id] was detached from
  /// its current parent object.
  ///
  /// The object will be detached permanently unless it is reattached via the
  /// [_attachObject] method.
  void _detachObject(int id) {
    final SemanticsObject? object = _semanticsTree[id];
    assert(object != null);
    if (object != null) {
      _detachments.add(object);
    }
  }

  /// Callbacks called after all objects in the tree have their properties
  /// populated and their sizes and locations computed.
  ///
  /// This list is reset to empty after all callbacks are called.
  List<ui.VoidCallback> _oneTimePostUpdateCallbacks = <ui.VoidCallback>[];

  /// Schedules a one-time callback to be called after all objects in the tree
  /// have their properties populated and their sizes and locations computed.
  void addOneTimePostUpdateCallback(ui.VoidCallback callback) {
    _oneTimePostUpdateCallbacks.add(callback);
  }

  /// Reconciles [_attachments] and [_detachments], and after that calls all
  /// the one-time callbacks scheduled via the [addOneTimePostUpdateCallback]
  /// method.
  void _finalizeTree() {
    // Collect all nodes that need to be permanently removed, i.e. nodes that
    // were detached from their parent, but not reattached to another parent.
    final Set<SemanticsObject> removals = <SemanticsObject>{};
    for (final SemanticsObject detachmentRoot in _detachments) {
      // A detached node may or may not have some of its descendants reattached
      // elsewhere. Walk the descendant tree and find all descendants that were
      // reattached to a parent. Those descendants need to be removed.
      detachmentRoot.visitDepthFirstInTraversalOrder((SemanticsObject node) {
        final SemanticsObject? parent = _attachments[node.id];
        if (parent == null) {
          // Was not reparented and is removed permanently from the tree.
          removals.add(node);
        } else {
          assert(node._parent == parent);
          assert(node.element.parentNode == parent._childContainerElement);
        }
        return true;
      });
    }

    for (final SemanticsObject removal in removals) {
      _semanticsTree.remove(removal.id);
      removal.dispose();
    }

    _detachments = <SemanticsObject>[];
    _attachments = <int, SemanticsObject>{};

    _phase = SemanticsUpdatePhase.postUpdate;
    try {
      if (_oneTimePostUpdateCallbacks.isNotEmpty) {
        for (final ui.VoidCallback callback in _oneTimePostUpdateCallbacks) {
          callback();
        }
        _oneTimePostUpdateCallbacks = <ui.VoidCallback>[];
      }
    } finally {
      _phase = SemanticsUpdatePhase.idle;
    }
    _hasNodeRequestingFocus = false;
  }

  /// Returns the entire semantics tree for testing.
  ///
  /// Works only in debug mode.
  Map<int, SemanticsObject>? get debugSemanticsTree {
    Map<int, SemanticsObject>? result;
    assert(() {
      result = _semanticsTree;
      return true;
    }());
    return result;
  }

  /// Looks up a [SemanticsObject] in the semantics tree by ID, or creates a new
  /// instance if it does not exist.
  SemanticsObject getOrCreateObject(int id) {
    SemanticsObject? object = _semanticsTree[id];
    if (object == null) {
      object = SemanticsObject(id, this);
      _semanticsTree[id] = object;
    }
    return object;
  }

  // Checks the consistency of the semantics node tree against the {ID: node}
  // map. The two must be in total agreement. Every node in the map must be
  // somewhere in the tree.
  (bool, String) _computeNodeMapConsistencyMessage() {
    final Map<int, List<int>> liveIds = <int, List<int>>{};

    final SemanticsObject? root = _semanticsTree[0];
    if (root != null) {
      root._debugVisitRenderedSemanticNodesDepthFirst((SemanticsObject child) {
        liveIds[child.id] = child._childrenInTraversalOrder?.toList() ?? const <int>[];
      });
    }

    final bool isConsistent = _semanticsTree.keys.every(liveIds.keys.contains);
    final String heading = 'The semantics node map is ${isConsistent ? 'consistent' : 'inconsistent'}';
    final StringBuffer message = StringBuffer('$heading:\n');
    message.writeln('  Nodes in tree:');
    for (final MapEntry<int, List<int>> entry in liveIds.entries) {
      message.writeln('    ${entry.key}: ${entry.value}');
    }
    message.writeln('  Nodes in map: [${_semanticsTree.keys.join(', ')}]');

    return (isConsistent, message.toString());
  }

  /// Updates the semantics tree from data in the [uiUpdate].
  void updateSemantics(ui.SemanticsUpdate uiUpdate) {
    EngineSemantics.instance.didReceiveSemanticsUpdate();

    if (!EngineSemantics.instance.semanticsEnabled) {
      return;
    }

    (bool, String)? preUpdateNodeMapConsistency;
    assert(() {
      preUpdateNodeMapConsistency = _computeNodeMapConsistencyMessage();
      return true;
    }());

    _phase = SemanticsUpdatePhase.updating;
    final SemanticsUpdate update = uiUpdate as SemanticsUpdate;

    // First, update each object's information about itself. This information is
    // later used to fix the parent-child and sibling relationships between
    // objects.
    final List<SemanticsNodeUpdate> nodeUpdates = update._nodeUpdates!;
    for (final SemanticsNodeUpdate nodeUpdate in nodeUpdates) {
      final SemanticsObject object = getOrCreateObject(nodeUpdate.id);
      object.updateSelf(nodeUpdate);
    }

    // Second, fix the tree structure. This is moved out into its own loop,
    // because each object's own information must be updated first.
    for (final SemanticsNodeUpdate nodeUpdate in nodeUpdates) {
      final SemanticsObject object = _semanticsTree[nodeUpdate.id]!;
      object.updateChildren();
      object._dirtyFields = 0;
    }

    final SemanticsObject root = _semanticsTree[0]!;
    if (_rootSemanticsElement == null) {
      _rootSemanticsElement = root.element;
      semanticsHost.append(root.element);
    }

    _finalizeTree();

    assert(() {
      // Validate that the node map only contains live elements, i.e. descendants
      // of the root node. If a node is not reachable from the root, it should
      // have been removed from the map.
      final (bool isConsistent, String description) = _computeNodeMapConsistencyMessage();
      if (!isConsistent) {
        // Use StateError because AssertionError escapes line breaks, but this
        // error message is very detailed and it needs line breaks for
        // legibility.
        throw StateError('''
Semantics node map was inconsistent after update:

BEFORE: ${preUpdateNodeMapConsistency?.$2}

AFTER: $description
''');
      }

      // Validate that each node in the final tree is self-consistent.
      _semanticsTree.forEach((int? id, SemanticsObject object) {
        assert(id == object.id);

        // Dirty fields should be cleared after the tree has been finalized.
        assert(object._dirtyFields == 0);

        // Make sure a child container is created only when there are children.
        assert(object._childContainerElement == null || object.hasChildren);

        // Ensure child ID list is consistent with the parent-child
        // relationship of the semantics tree.
        if (object._childrenInTraversalOrder != null) {
          for (final int childId in object._childrenInTraversalOrder!) {
            final SemanticsObject? child = _semanticsTree[childId];
            if (child == null) {
              throw AssertionError('Child #$childId is missing in the tree.');
            }
            if (child._parent == null) {
              throw AssertionError(
                  'Child #$childId of parent #${object.id} has null parent '
                  'reference.');
            }
            if (!identical(child._parent, object)) {
              throw AssertionError(
                  'Parent #${object.id} has child #$childId. However, the '
                  'child is attached to #${child._parent!.id}.');
            }
          }
        }
      });

      // Validate that all updates were applied
      for (final SemanticsNodeUpdate update in nodeUpdates) {
        // Node was added to the tree.
        assert(_semanticsTree.containsKey(update.id));
      }

      // Verify that `update._nodeUpdates` has not changed.
      assert(identical(update._nodeUpdates, nodeUpdates));

      return true;
    }());
  }

  /// Removes the semantics tree for this view from the page and collects all
  /// resources.
  ///
  /// The object remains usable after this operation, but because the previous
  /// semantics tree is completely removed, partial udpates will not succeed as
  /// they rely on the prior state of the tree. There is no distinction between
  /// a full update and partial update, so the failure may be cryptic.
  void reset() {
    final List<int> keys = _semanticsTree.keys.toList();
    final int len = keys.length;
    for (int i = 0; i < len; i++) {
      _detachObject(keys[i]);
    }
    _finalizeTree();
    _rootSemanticsElement?.remove();
    _rootSemanticsElement = null;
    _semanticsTree.clear();
    _attachments.clear();
    _detachments.clear();
    _phase = SemanticsUpdatePhase.idle;
    _oneTimePostUpdateCallbacks.clear();
  }

  /// True, if any semantics node requested focus explicitly during the latest
  /// semantics update.
  ///
  /// The default value is `false`, and it is reset back to `false` after the
  /// semantics update at the end of [updateSemantics].
  ///
  /// Since focus can only be taken by no more than one element, the engine
  /// should not request focus for multiple elements. This flag helps resolve
  /// that.
  bool get hasNodeRequestingFocus => _hasNodeRequestingFocus;
  bool _hasNodeRequestingFocus = false;

  /// Declares that a semantics node will explicitly request focus.
  ///
  /// This prevents others, [Dialog] in particular, from requesting autofocus,
  /// as focus can only be taken by one element. Explicit focus has higher
  /// precedence than autofocus.
  void willRequestFocus() {
    _hasNodeRequestingFocus = true;
  }
}

/// Computes the [longest increasing subsequence](http://en.wikipedia.org/wiki/Longest_increasing_subsequence).
///
/// Returns list of indices (rather than values) into [list].
///
/// Complexity: n*log(n)
List<int> longestIncreasingSubsequence(List<int> list) {
  final int len = list.length;
  final List<int> predecessors = <int>[];
  final List<int> mins = <int>[0];
  int longest = 0;
  for (int i = 0; i < len; i++) {
    // Binary search for the largest positive `j ≤ longest`
    // such that `list[mins[j]] < list[i]`
    final int elem = list[i];
    int lo = 1;
    int hi = longest;
    while (lo <= hi) {
      final int mid = (lo + hi) ~/ 2;
      if (list[mins[mid]] < elem) {
        lo = mid + 1;
      } else {
        hi = mid - 1;
      }
    }
    // After searching, `lo` is 1 greater than the
    // length of the longest prefix of `list[i]`
    final int expansionIndex = lo;
    // The predecessor of `list[i]` is the last index of
    // the subsequence of length `newLongest - 1`
    predecessors.add(mins[expansionIndex - 1]);
    if (expansionIndex >= mins.length) {
      mins.add(i);
    } else {
      mins[expansionIndex] = i;
    }
    if (expansionIndex > longest) {
      // Record the longest subsequence found so far.
      longest = expansionIndex;
    }
  }
  // Reconstruct the longest subsequence
  final List<int> seq = List<int>.filled(longest, 0);
  int k = mins[longest];
  for (int i = longest - 1; i >= 0; i--) {
    seq[i] = k;
    k = predecessors[k];
  }
  return seq;
}

/// States that a [ui.SemanticsNode] can have.
///
/// SemanticsNodes can be in three distinct states (enabled, disabled,
/// no opinion).
enum EnabledState {
  /// Flag [ui.SemanticsFlag.hasEnabledState] is not set.
  ///
  /// The node does not have enabled/disabled state.
  noOpinion,

  /// Flag [ui.SemanticsFlag.hasEnabledState] and [ui.SemanticsFlag.isEnabled]
  /// are set.
  ///
  /// The node is enabled.
  enabled,

  /// Flag [ui.SemanticsFlag.hasEnabledState] is set and
  /// [ui.SemanticsFlag.isEnabled] is not set.
  ///
  /// The node is disabled.
  disabled,
}
