// Copyright 2014 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:ui' show Offset, Rect, SemanticsAction, SemanticsFlag, SemanticsUpdate, SemanticsUpdateBuilder, StringAttribute, TextDirection;

import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart' show MatrixUtils, TransformProperty;
import 'package:flutter/services.dart';
import 'package:vector_math/vector_math_64.dart';

import 'binding.dart' show SemanticsBinding;
import 'semantics_event.dart';

export 'dart:ui' show Offset, Rect, SemanticsAction, SemanticsFlag, StringAttribute, TextDirection, VoidCallback;

export 'package:flutter/foundation.dart' show DiagnosticLevel, DiagnosticPropertiesBuilder, DiagnosticsNode, DiagnosticsTreeStyle, Key, TextTreeConfiguration;
export 'package:flutter/services.dart' show TextSelection;
export 'package:vector_math/vector_math_64.dart' show Matrix4;

export 'semantics_event.dart' show SemanticsEvent;

/// Signature for a function that is called for each [SemanticsNode].
///
/// Return false to stop visiting nodes.
///
/// Used by [SemanticsNode.visitChildren].
typedef SemanticsNodeVisitor = bool Function(SemanticsNode node);

/// Signature for [SemanticsAction]s that move the cursor.
///
/// If `extendSelection` is set to true the cursor movement should extend the
/// current selection or (if nothing is currently selected) start a selection.
typedef MoveCursorHandler = void Function(bool extendSelection);

/// Signature for the [SemanticsAction.setSelection] handlers to change the
/// text selection (or re-position the cursor) to `selection`.
typedef SetSelectionHandler = void Function(TextSelection selection);

/// Signature for the [SemanticsAction.setText] handlers to replace the
/// current text with the input `text`.
typedef SetTextHandler = void Function(String text);

/// Signature for a handler of a [SemanticsAction].
///
/// Returned by [SemanticsConfiguration.getActionHandler].
typedef SemanticsActionHandler = void Function(Object? args);

/// Signature for a function that receives a semantics update and returns no result.
///
/// Used by [SemanticsOwner.onSemanticsUpdate].
typedef SemanticsUpdateCallback = void Function(SemanticsUpdate update);

/// Signature for the [SemanticsConfiguration.childConfigurationsDelegate].
///
/// The input list contains all [SemanticsConfiguration]s that rendering
/// children want to merge upward. One can tag a render child with a
/// [SemanticsTag] and look up its [SemanticsConfiguration]s through
/// [SemanticsConfiguration.tagsChildrenWith].
///
/// The return value is the arrangement of these configs, including which
/// configs continue to merge upward and which configs form sibling merge group.
///
/// Use [ChildSemanticsConfigurationsResultBuilder] to generate the return
/// value.
typedef ChildSemanticsConfigurationsDelegate = ChildSemanticsConfigurationsResult Function(List<SemanticsConfiguration>);

final int _kUnblockedUserActions = SemanticsAction.didGainAccessibilityFocus.index
  | SemanticsAction.didLoseAccessibilityFocus.index;

/// A tag for a [SemanticsNode].
///
/// Tags can be interpreted by the parent of a [SemanticsNode]
/// and depending on the presence of a tag the parent can for example decide
/// how to add the tagged node as a child. Tags are not sent to the engine.
///
/// As an example, the [RenderSemanticsGestureHandler] uses tags to determine
/// if a child node should be excluded from the scrollable area for semantic
/// purposes.
///
/// The provided [name] is only used for debugging. Two tags created with the
/// same [name] and the `new` operator are not considered identical. However,
/// two tags created with the same [name] and the `const` operator are always
/// identical.
class SemanticsTag {
  /// Creates a [SemanticsTag].
  ///
  /// The provided [name] is only used for debugging. Two tags created with the
  /// same [name] and the `new` operator are not considered identical. However,
  /// two tags created with the same [name] and the `const` operator are always
  /// identical.
  const SemanticsTag(this.name);

  /// A human-readable name for this tag used for debugging.
  ///
  /// This string is not used to determine if two tags are identical.
  final String name;

  @override
  String toString() => '${objectRuntimeType(this, 'SemanticsTag')}($name)';
}

/// The result that contains the arrangement for the child
/// [SemanticsConfiguration]s.
///
/// When the [PipelineOwner] builds the semantics tree, it uses the returned
/// [ChildSemanticsConfigurationsResult] from
/// [SemanticsConfiguration.childConfigurationsDelegate] to decide how semantics nodes
/// should form.
///
/// Use [ChildSemanticsConfigurationsResultBuilder] to build the result.
class ChildSemanticsConfigurationsResult {
  ChildSemanticsConfigurationsResult._(this.mergeUp, this.siblingMergeGroups);

  /// Returns the [SemanticsConfiguration]s that are supposed to be merged into
  /// the parent semantics node.
  ///
  /// [SemanticsConfiguration]s that are either semantics boundaries or are
  /// conflicting with other [SemanticsConfiguration]s will form explicit
  /// semantics nodes. All others will be merged into the parent.
  final List<SemanticsConfiguration> mergeUp;

  /// The groups of child semantics configurations that want to merge together
  /// and form a sibling [SemanticsNode].
  ///
  /// All the [SemanticsConfiguration]s in a given group that are either
  /// semantics boundaries or are conflicting with other
  /// [SemanticsConfiguration]s of the same group will be excluded from the
  /// sibling merge group and form independent semantics nodes as usual.
  ///
  /// The result [SemanticsNode]s from the merges are attached as the sibling
  /// nodes of the immediate parent semantics node. For example, a `RenderObjectA`
  /// has a rendering child, `RenderObjectB`. If both of them form their own
  /// semantics nodes, `SemanticsNodeA` and `SemanticsNodeB`, any semantics node
  /// created from sibling merge groups of `RenderObjectB` will be attach to
  /// `SemanticsNodeA` as a sibling of `SemanticsNodeB`.
  final List<List<SemanticsConfiguration>> siblingMergeGroups;
}

/// The builder to build a [ChildSemanticsConfigurationsResult] based on its
/// annotations.
///
/// To use this builder, one can use [markAsMergeUp] and
/// [markAsSiblingMergeGroup] to annotate the arrangement of
/// [SemanticsConfiguration]s. Once all the configs are annotated, use [build]
/// to generate the [ChildSemanticsConfigurationsResult].
class ChildSemanticsConfigurationsResultBuilder {
  /// Creates a [ChildSemanticsConfigurationsResultBuilder].
  ChildSemanticsConfigurationsResultBuilder();

  final List<SemanticsConfiguration> _mergeUp = <SemanticsConfiguration>[];
  final List<List<SemanticsConfiguration>> _siblingMergeGroups = <List<SemanticsConfiguration>>[];

  /// Marks the [SemanticsConfiguration] to be merged into the parent semantics
  /// node.
  ///
  /// The [SemanticsConfiguration] will be added to the
  /// [ChildSemanticsConfigurationsResult.mergeUp] that this builder builds.
  void markAsMergeUp(SemanticsConfiguration config) => _mergeUp.add(config);

  /// Marks a group of [SemanticsConfiguration]s to merge together
  /// and form a sibling [SemanticsNode].
  ///
  /// The group of [SemanticsConfiguration]s will be added to the
  /// [ChildSemanticsConfigurationsResult.siblingMergeGroups] that this builder builds.
  void markAsSiblingMergeGroup(List<SemanticsConfiguration> configs) => _siblingMergeGroups.add(configs);

  /// Builds a [ChildSemanticsConfigurationsResult] contains the arrangement.
  ChildSemanticsConfigurationsResult build() {
    assert((){
      final Set<SemanticsConfiguration> seenConfigs = <SemanticsConfiguration>{};
      for (final SemanticsConfiguration config in <SemanticsConfiguration>[..._mergeUp, ..._siblingMergeGroups.flattened]) {
        assert(
          seenConfigs.add(config),
          'Duplicated SemanticsConfigurations. This can happen if the same '
          'SemanticsConfiguration was marked twice in markAsMergeUp and/or '
          'markAsSiblingMergeGroup'
        );
      }
      return true;
    }());
    return ChildSemanticsConfigurationsResult._(_mergeUp, _siblingMergeGroups);
  }
}

/// An identifier of a custom semantics action.
///
/// Custom semantics actions can be provided to make complex user
/// interactions more accessible. For instance, if an application has a
/// drag-and-drop list that requires the user to press and hold an item
/// to move it, users interacting with the application using a hardware
/// switch may have difficulty. This can be made accessible by creating custom
/// actions and pairing them with handlers that move a list item up or down in
/// the list.
///
/// In Android, these actions are presented in the local context menu. In iOS,
/// these are presented in the radial context menu.
///
/// Localization and text direction do not automatically apply to the provided
/// label or hint.
///
/// Instances of this class should either be instantiated with const or
/// new instances cached in static fields.
///
/// See also:
///
///  * [SemanticsProperties], where the handler for a custom action is provided.
@immutable
class CustomSemanticsAction {
  /// Creates a new [CustomSemanticsAction].
  ///
  /// The [label] must not be null or the empty string.
  const CustomSemanticsAction({required String this.label})
    : assert(label != ''),
      hint = null,
      action = null;

  /// Creates a new [CustomSemanticsAction] that overrides a standard semantics
  /// action.
  ///
  /// The [hint] must not be null or the empty string.
  const CustomSemanticsAction.overridingAction({required String this.hint, required SemanticsAction this.action})
    : assert(hint != ''),
      label = null;

  /// The user readable name of this custom semantics action.
  final String? label;

  /// The hint description of this custom semantics action.
  final String? hint;

  /// The standard semantics action this action replaces.
  final SemanticsAction? action;

  @override
  int get hashCode => Object.hash(label, hint, action);

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is CustomSemanticsAction
        && other.label == label
        && other.hint == hint
        && other.action == action;
  }

  @override
  String toString() {
    return 'CustomSemanticsAction(${_ids[this]}, label:$label, hint:$hint, action:$action)';
  }

  // Logic to assign a unique id to each custom action without requiring
  // user specification.
  static int _nextId = 0;
  static final Map<int, CustomSemanticsAction> _actions = <int, CustomSemanticsAction>{};
  static final Map<CustomSemanticsAction, int> _ids = <CustomSemanticsAction, int>{};

  /// Get the identifier for a given `action`.
  static int getIdentifier(CustomSemanticsAction action) {
    int? result = _ids[action];
    if (result == null) {
      result = _nextId++;
      _ids[action] = result;
      _actions[result] = action;
    }
    return result;
  }

  /// Get the `action` for a given identifier.
  static CustomSemanticsAction? getAction(int id) {
    return _actions[id];
  }
}

/// A string that carries a list of [StringAttribute]s.
@immutable
class AttributedString {
  /// Creates a attributed string.
  ///
  /// The [TextRange] in the [attributes] must be inside the length of the
  /// [string].
  ///
  /// The [attributes] must not be changed after the attributed string is
  /// created.
  AttributedString(
    this.string, {
    this.attributes = const <StringAttribute>[],
  }) : assert(string.isNotEmpty || attributes.isEmpty),
       assert(() {
        for (final StringAttribute attribute in attributes) {
          assert(
            string.length >= attribute.range.start &&
            string.length >= attribute.range.end,
            'The range in $attribute is outside of the string $string',
          );
        }
        return true;
      }());

  /// The plain string stored in the attributed string.
  final String string;

  /// The attributes this string carries.
  ///
  /// The list must not be modified after this string is created.
  final List<StringAttribute> attributes;

  /// Returns a new [AttributedString] by concatenate the operands
  ///
  /// The string attribute list of the returned [AttributedString] will contains
  /// the string attributes from both operands with updated text ranges.
  AttributedString operator +(AttributedString other) {
    if (string.isEmpty) {
      return other;
    }
    if (other.string.isEmpty) {
      return this;
    }

    // None of the strings is empty.
    final String newString = string + other.string;
    final List<StringAttribute> newAttributes = List<StringAttribute>.of(attributes);
    if (other.attributes.isNotEmpty) {
      final int offset = string.length;
      for (final StringAttribute attribute in other.attributes) {
        final TextRange newRange = TextRange(
          start: attribute.range.start + offset,
          end: attribute.range.end + offset,
        );
        final StringAttribute adjustedAttribute = attribute.copy(range: newRange);
        newAttributes.add(adjustedAttribute);
      }
    }
    return AttributedString(newString, attributes: newAttributes);
  }

  /// Two [AttributedString]s are equal if their string and attributes are.
  @override
  bool operator ==(Object other) {
    return other.runtimeType == runtimeType
        && other is AttributedString
        && other.string == string
        && listEquals<StringAttribute>(other.attributes, attributes);
  }

  @override
  int get hashCode => Object.hash(string, attributes);

  @override
  String toString() {
    return "${objectRuntimeType(this, 'AttributedString')}('$string', attributes: $attributes)";
  }
}

/// A [DiagnosticsProperty] for [AttributedString]s, which shows a string
/// when there are no attributes, and more details otherwise.
class AttributedStringProperty extends DiagnosticsProperty<AttributedString> {
  /// Create a diagnostics property for an [AttributedString] object.
  ///
  /// Such properties are used with [SemanticsData] objects.
  AttributedStringProperty(
    String super.name,
    super.value, {
    super.showName,
    this.showWhenEmpty = false,
    super.defaultValue,
    super.level,
    super.description,
  });

  /// Whether to show the property when the [value] is an [AttributedString]
  /// whose [AttributedString.string] is the empty string.
  ///
  /// This overrides [defaultValue].
  final bool showWhenEmpty;

  @override
  bool get isInteresting => super.isInteresting && (showWhenEmpty || (value != null && value!.string.isNotEmpty));

  @override
  String valueToString({TextTreeConfiguration? parentConfiguration}) {
    if (value == null) {
      return 'null';
    }
    String text = value!.string;
    if (parentConfiguration != null &&
        !parentConfiguration.lineBreakProperties) {
      // This follows a similar pattern to StringProperty.
      text = text.replaceAll('\n', r'\n');
    }
    if (value!.attributes.isEmpty) {
      return '"$text"';
    }
    return '"$text" ${value!.attributes}'; // the attributes will be in square brackets since they're a list
  }
}

/// Summary information about a [SemanticsNode] object.
///
/// A semantics node might [SemanticsNode.mergeAllDescendantsIntoThisNode],
/// which means the individual fields on the semantics node don't fully describe
/// the semantics at that node. This data structure contains the full semantics
/// for the node.
///
/// Typically obtained from [SemanticsNode.getSemanticsData].
@immutable
class SemanticsData with Diagnosticable {
  /// Creates a semantics data object.
  ///
  /// The [flags], [actions], [label], and [Rect] arguments must not be null.
  ///
  /// If [label] is not empty, then [textDirection] must also not be null.
  SemanticsData({
    required this.flags,
    required this.actions,
    required this.attributedLabel,
    required this.attributedValue,
    required this.attributedIncreasedValue,
    required this.attributedDecreasedValue,
    required this.attributedHint,
    required this.tooltip,
    required this.textDirection,
    required this.rect,
    required this.elevation,
    required this.thickness,
    required this.textSelection,
    required this.scrollIndex,
    required this.scrollChildCount,
    required this.scrollPosition,
    required this.scrollExtentMax,
    required this.scrollExtentMin,
    required this.platformViewId,
    required this.maxValueLength,
    required this.currentValueLength,
    this.tags,
    this.transform,
    this.customSemanticsActionIds,
  }) : assert(tooltip == '' || textDirection != null, 'A SemanticsData object with tooltip "$tooltip" had a null textDirection.'),
       assert(attributedLabel.string == '' || textDirection != null, 'A SemanticsData object with label "${attributedLabel.string}" had a null textDirection.'),
       assert(attributedValue.string == '' || textDirection != null, 'A SemanticsData object with value "${attributedValue.string}" had a null textDirection.'),
       assert(attributedDecreasedValue.string == '' || textDirection != null, 'A SemanticsData object with decreasedValue "${attributedDecreasedValue.string}" had a null textDirection.'),
       assert(attributedIncreasedValue.string == '' || textDirection != null, 'A SemanticsData object with increasedValue "${attributedIncreasedValue.string}" had a null textDirection.'),
       assert(attributedHint.string == '' || textDirection != null, 'A SemanticsData object with hint "${attributedHint.string}" had a null textDirection.');

  /// A bit field of [SemanticsFlag]s that apply to this node.
  final int flags;

  /// A bit field of [SemanticsAction]s that apply to this node.
  final int actions;

  /// A textual description for the current label of the node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedLabel].
  String get label => attributedLabel.string;

  /// A textual description for the current label of the node in
  /// [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [label], which exposes just the raw text.
  final AttributedString attributedLabel;

  /// A textual description for the current value of the node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedValue].
  String get value => attributedValue.string;

  /// A textual description for the current value of the node in
  /// [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [value], which exposes just the raw text.
  final AttributedString attributedValue;

  /// The value that [value] will become after performing a
  /// [SemanticsAction.increase] action.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedIncreasedValue].
  String get increasedValue => attributedIncreasedValue.string;

  /// The value that [value] will become after performing a
  /// [SemanticsAction.increase] action in [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [increasedValue], which exposes just the raw text.
  final AttributedString attributedIncreasedValue;

  /// The value that [value] will become after performing a
  /// [SemanticsAction.decrease] action.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedDecreasedValue].
  String get decreasedValue => attributedDecreasedValue.string;

  /// The value that [value] will become after performing a
  /// [SemanticsAction.decrease] action in [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [decreasedValue], which exposes just the raw text.
  final AttributedString attributedDecreasedValue;

  /// A brief description of the result of performing an action on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedHint].
  String get hint => attributedHint.string;

  /// A brief description of the result of performing an action on this node
  /// in [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [hint], which exposes just the raw text.
  final AttributedString attributedHint;

  /// A textual description of the widget's tooltip.
  ///
  /// The reading direction is given by [textDirection].
  final String tooltip;

  /// The reading direction for the text in [label], [value],
  /// [increasedValue], [decreasedValue], and [hint].
  final TextDirection? textDirection;

  /// The currently selected text (or the position of the cursor) within [value]
  /// if this node represents a text field.
  final TextSelection? textSelection;

  /// The total number of scrollable children that contribute to semantics.
  ///
  /// If the number of children are unknown or unbounded, this value will be
  /// null.
  final int? scrollChildCount;

  /// The index of the first visible semantic child of a scroll node.
  final int? scrollIndex;

  /// Indicates the current scrolling position in logical pixels if the node is
  /// scrollable.
  ///
  /// The properties [scrollExtentMin] and [scrollExtentMax] indicate the valid
  /// in-range values for this property. The value for [scrollPosition] may
  /// (temporarily) be outside that range, e.g. during an overscroll.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.pixels], from where this value is usually taken.
  final double? scrollPosition;

  /// Indicates the maximum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.maxScrollExtent], from where this value is usually taken.
  final double? scrollExtentMax;

  /// Indicates the minimum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.minScrollExtent], from where this value is usually taken.
  final double? scrollExtentMin;

  /// The id of the platform view, whose semantics nodes will be added as
  /// children to this node.
  ///
  /// If this value is non-null, the SemanticsNode must not have any children
  /// as those would be replaced by the semantics nodes of the referenced
  /// platform view.
  ///
  /// See also:
  ///
  ///  * [AndroidView], which is the platform view for Android.
  ///  * [UiKitView], which is the platform view for iOS.
  final int? platformViewId;

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. Defaults
  /// to null, which means no limit is imposed on the text field.
  final int? maxValueLength;

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. This must
  /// be set when [maxValueLength] is set.
  final int? currentValueLength;

  /// The bounding box for this node in its coordinate system.
  final Rect rect;

  /// The set of [SemanticsTag]s associated with this node.
  final Set<SemanticsTag>? tags;

  /// The transform from this node's coordinate system to its parent's coordinate system.
  ///
  /// By default, the transform is null, which represents the identity
  /// transformation (i.e., that this node has the same coordinate system as its
  /// parent).
  final Matrix4? transform;

  /// The elevation of this node relative to the parent semantics node.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.elevation] for a detailed discussion regarding
  ///    elevation and semantics.
  final double elevation;

  /// The extent of this node along the z-axis beyond its [elevation]
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.thickness] for a more detailed definition.
  final double thickness;

  /// The identifiers for the custom semantics actions and standard action
  /// overrides for this node.
  ///
  /// The list must be sorted in increasing order.
  ///
  /// See also:
  ///
  ///  * [CustomSemanticsAction], for an explanation of custom actions.
  final List<int>? customSemanticsActionIds;

  /// Whether [flags] contains the given flag.
  bool hasFlag(SemanticsFlag flag) => (flags & flag.index) != 0;

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

  @override
  String toStringShort() => objectRuntimeType(this, 'SemanticsData');

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<Rect>('rect', rect, showName: false));
    properties.add(TransformProperty('transform', transform, showName: false, defaultValue: null));
    properties.add(DoubleProperty('elevation', elevation, defaultValue: 0.0));
    properties.add(DoubleProperty('thickness', thickness, defaultValue: 0.0));
    final List<String> actionSummary = <String>[
      for (final SemanticsAction action in SemanticsAction.values)
        if ((actions & action.index) != 0)
          action.name,
    ];
    final List<String?> customSemanticsActionSummary = customSemanticsActionIds!
      .map<String?>((int actionId) => CustomSemanticsAction.getAction(actionId)!.label)
      .toList();
    properties.add(IterableProperty<String>('actions', actionSummary, ifEmpty: null));
    properties.add(IterableProperty<String?>('customActions', customSemanticsActionSummary, ifEmpty: null));

    final List<String> flagSummary = <String>[
      for (final SemanticsFlag flag in SemanticsFlag.values)
        if ((flags & flag.index) != 0)
          flag.name,
    ];
    properties.add(IterableProperty<String>('flags', flagSummary, ifEmpty: null));
    properties.add(AttributedStringProperty('label', attributedLabel));
    properties.add(AttributedStringProperty('value', attributedValue));
    properties.add(AttributedStringProperty('increasedValue', attributedIncreasedValue));
    properties.add(AttributedStringProperty('decreasedValue', attributedDecreasedValue));
    properties.add(AttributedStringProperty('hint', attributedHint));
    properties.add(StringProperty('tooltip', tooltip, defaultValue: ''));
    properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
    if (textSelection?.isValid ?? false) {
      properties.add(MessageProperty('textSelection', '[${textSelection!.start}, ${textSelection!.end}]'));
    }
    properties.add(IntProperty('platformViewId', platformViewId, defaultValue: null));
    properties.add(IntProperty('maxValueLength', maxValueLength, defaultValue: null));
    properties.add(IntProperty('currentValueLength', currentValueLength, defaultValue: null));
    properties.add(IntProperty('scrollChildren', scrollChildCount, defaultValue: null));
    properties.add(IntProperty('scrollIndex', scrollIndex, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMin', scrollExtentMin, defaultValue: null));
    properties.add(DoubleProperty('scrollPosition', scrollPosition, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMax', scrollExtentMax, defaultValue: null));
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticsData
        && other.flags == flags
        && other.actions == actions
        && other.attributedLabel == attributedLabel
        && other.attributedValue == attributedValue
        && other.attributedIncreasedValue == attributedIncreasedValue
        && other.attributedDecreasedValue == attributedDecreasedValue
        && other.attributedHint == attributedHint
        && other.tooltip == tooltip
        && other.textDirection == textDirection
        && other.rect == rect
        && setEquals(other.tags, tags)
        && other.scrollChildCount == scrollChildCount
        && other.scrollIndex == scrollIndex
        && other.textSelection == textSelection
        && other.scrollPosition == scrollPosition
        && other.scrollExtentMax == scrollExtentMax
        && other.scrollExtentMin == scrollExtentMin
        && other.platformViewId == platformViewId
        && other.maxValueLength == maxValueLength
        && other.currentValueLength == currentValueLength
        && other.transform == transform
        && other.elevation == elevation
        && other.thickness == thickness
        && _sortedListsEqual(other.customSemanticsActionIds, customSemanticsActionIds);
  }

  @override
  int get hashCode => Object.hash(
    flags,
    actions,
    attributedLabel,
    attributedValue,
    attributedIncreasedValue,
    attributedDecreasedValue,
    attributedHint,
    tooltip,
    textDirection,
    rect,
    tags,
    textSelection,
    scrollChildCount,
    scrollIndex,
    scrollPosition,
    scrollExtentMax,
    scrollExtentMin,
    platformViewId,
    maxValueLength,
    Object.hash(
      currentValueLength,
      transform,
      elevation,
      thickness,
      customSemanticsActionIds == null ? null : Object.hashAll(customSemanticsActionIds!),
    ),
  );

  static bool _sortedListsEqual(List<int>? left, List<int>? right) {
    if (left == null && right == null) {
      return true;
    }
    if (left != null && right != null) {
      if (left.length != right.length) {
        return false;
      }
      for (int i = 0; i < left.length; i++) {
        if (left[i] != right[i]) {
          return false;
      }
        }
      return true;
    }
    return false;
  }
}

class _SemanticsDiagnosticableNode extends DiagnosticableNode<SemanticsNode> {
  _SemanticsDiagnosticableNode({
    super.name,
    required super.value,
    required super.style,
    required this.childOrder,
  });

  final DebugSemanticsDumpOrder childOrder;

  @override
  List<DiagnosticsNode> getChildren() => value.debugDescribeChildren(childOrder: childOrder);
}

/// Provides hint values which override the default hints on supported
/// platforms.
///
/// On iOS, these values are always ignored.
@immutable
class SemanticsHintOverrides extends DiagnosticableTree {
  /// Creates a semantics hint overrides.
  const SemanticsHintOverrides({
    this.onTapHint,
    this.onLongPressHint,
  }) : assert(onTapHint != ''),
       assert(onLongPressHint != '');

  /// The hint text for a tap action.
  ///
  /// If null, the standard hint is used instead.
  ///
  /// The hint should describe what happens when a tap occurs, not the
  /// manner in which a tap is accomplished.
  ///
  /// Bad: 'Double tap to show movies'.
  /// Good: 'show movies'.
  final String? onTapHint;

  /// The hint text for a long press action.
  ///
  /// If null, the standard hint is used instead.
  ///
  /// The hint should describe what happens when a long press occurs, not
  /// the manner in which the long press is accomplished.
  ///
  /// Bad: 'Double tap and hold to show tooltip'.
  /// Good: 'show tooltip'.
  final String? onLongPressHint;

  /// Whether there are any non-null hint values.
  bool get isNotEmpty => onTapHint != null || onLongPressHint != null;

  @override
  int get hashCode => Object.hash(onTapHint, onLongPressHint);

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

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('onTapHint', onTapHint, defaultValue: null));
    properties.add(StringProperty('onLongPressHint', onLongPressHint, defaultValue: null));
  }
}

/// Contains properties used by assistive technologies to make the application
/// more accessible.
///
/// The properties of this class are used to generate a [SemanticsNode]s in the
/// semantics tree.
@immutable
class SemanticsProperties extends DiagnosticableTree {
  /// Creates a semantic annotation.
  const SemanticsProperties({
    this.enabled,
    this.checked,
    this.mixed,
    this.selected,
    this.toggled,
    this.button,
    this.link,
    this.header,
    this.textField,
    this.slider,
    this.keyboardKey,
    this.readOnly,
    this.focusable,
    this.focused,
    this.inMutuallyExclusiveGroup,
    this.hidden,
    this.obscured,
    this.multiline,
    this.scopesRoute,
    this.namesRoute,
    this.image,
    this.liveRegion,
    this.maxValueLength,
    this.currentValueLength,
    this.label,
    this.attributedLabel,
    this.value,
    this.attributedValue,
    this.increasedValue,
    this.attributedIncreasedValue,
    this.decreasedValue,
    this.attributedDecreasedValue,
    this.hint,
    this.tooltip,
    this.attributedHint,
    this.hintOverrides,
    this.textDirection,
    this.sortKey,
    this.tagForChildren,
    this.onTap,
    this.onLongPress,
    this.onScrollLeft,
    this.onScrollRight,
    this.onScrollUp,
    this.onScrollDown,
    this.onIncrease,
    this.onDecrease,
    this.onCopy,
    this.onCut,
    this.onPaste,
    this.onMoveCursorForwardByCharacter,
    this.onMoveCursorBackwardByCharacter,
    this.onMoveCursorForwardByWord,
    this.onMoveCursorBackwardByWord,
    this.onSetSelection,
    this.onSetText,
    this.onDidGainAccessibilityFocus,
    this.onDidLoseAccessibilityFocus,
    this.onDismiss,
    this.customSemanticsActions,
  }) : assert(label == null || attributedLabel == null, 'Only one of label or attributedLabel should be provided'),
       assert(value == null || attributedValue == null, 'Only one of value or attributedValue should be provided'),
       assert(increasedValue == null || attributedIncreasedValue == null, 'Only one of increasedValue or attributedIncreasedValue should be provided'),
       assert(decreasedValue == null || attributedDecreasedValue == null, 'Only one of decreasedValue or attributedDecreasedValue should be provided'),
       assert(hint == null || attributedHint == null, 'Only one of hint or attributedHint should be provided');

  /// If non-null, indicates that this subtree represents something that can be
  /// in an enabled or disabled state.
  ///
  /// For example, a button that a user can currently interact with would set
  /// this field to true. A button that currently does not respond to user
  /// interactions would set this field to false.
  final bool? enabled;

  /// If non-null, indicates that this subtree represents a checkbox
  /// or similar widget with a "checked" state, and what its current
  /// state is.
  ///
  /// When the [Checkbox.value] of a tristate Checkbox is null,
  /// indicating a mixed-state, this value shall be false, in which
  /// case, [mixed] will be true.
  ///
  /// This is mutually exclusive with [toggled] and [mixed].
  final bool? checked;

  /// If non-null, indicates that this subtree represents a checkbox
  /// or similar widget with a "half-checked" state or similar, and
  /// whether it is currently in this half-checked state.
  ///
  /// This must be null when [Checkbox.tristate] is false, or
  /// when the widget is not a checkbox. When a tristate
  /// checkbox is fully unchecked/checked, this value shall
  /// be false.
  ///
  /// This is mutually exclusive with [checked] and [toggled].
  final bool? mixed;

  /// If non-null, indicates that this subtree represents a toggle switch
  /// or similar widget with an "on" state, and what its current
  /// state is.
  ///
  /// This is mutually exclusive with [checked] and [mixed].
  final bool? toggled;

  /// If non-null indicates that this subtree represents something that can be
  /// in a selected or unselected state, and what its current state is.
  ///
  /// The active tab in a tab bar for example is considered "selected", whereas
  /// all other tabs are unselected.
  final bool? selected;

  /// If non-null, indicates that this subtree represents a button.
  ///
  /// TalkBack/VoiceOver provides users with the hint "button" when a button
  /// is focused.
  final bool? button;

  /// If non-null, indicates that this subtree represents a link.
  ///
  /// iOS's VoiceOver provides users with a unique hint when a link is focused.
  /// Android's Talkback will announce a link hint the same way it does a
  /// button.
  final bool? link;

  /// If non-null, indicates that this subtree represents a header.
  ///
  /// A header divides into sections. For example, an address book application
  /// might define headers A, B, C, etc. to divide the list of alphabetically
  /// sorted contacts into sections.
  final bool? header;

  /// If non-null, indicates that this subtree represents a text field.
  ///
  /// TalkBack/VoiceOver provide special affordances to enter text into a
  /// text field.
  final bool? textField;

  /// If non-null, indicates that this subtree represents a slider.
  ///
  /// Talkback/\VoiceOver provides users with the hint "slider" when a
  /// slider is focused.
  final bool? slider;

  /// If non-null, indicates that this subtree represents a keyboard key.
  final bool? keyboardKey;

  /// If non-null, indicates that this subtree is read only.
  ///
  /// Only applicable when [textField] is true.
  ///
  /// TalkBack/VoiceOver will treat it as non-editable text field.
  final bool? readOnly;

  /// If non-null, whether the node is able to hold input focus.
  ///
  /// If [focusable] is set to false, then [focused] must not be true.
  ///
  /// Input focus indicates that the node will receive keyboard events. It is not
  /// to be confused with accessibility focus. Accessibility focus is the
  /// green/black rectangular highlight that TalkBack/VoiceOver draws around the
  /// element it is reading, and is separate from input focus.
  final bool? focusable;

  /// If non-null, whether the node currently holds input focus.
  ///
  /// At most one node in the tree should hold input focus at any point in time,
  /// and it should not be set to true if [focusable] is false.
  ///
  /// Input focus indicates that the node will receive keyboard events. It is not
  /// to be confused with accessibility focus. Accessibility focus is the
  /// green/black rectangular highlight that TalkBack/VoiceOver draws around the
  /// element it is reading, and is separate from input focus.
  final bool? focused;

  /// If non-null, whether a semantic node is in a mutually exclusive group.
  ///
  /// For example, a radio button is in a mutually exclusive group because only
  /// one radio button in that group can be marked as [checked].
  final bool? inMutuallyExclusiveGroup;

  /// If non-null, whether the node is considered hidden.
  ///
  /// Hidden elements are currently not visible on screen. They may be covered
  /// by other elements or positioned outside of the visible area of a viewport.
  ///
  /// Hidden elements cannot gain accessibility focus though regular touch. The
  /// only way they can be focused is by moving the focus to them via linear
  /// navigation.
  ///
  /// Platforms are free to completely ignore hidden elements and new platforms
  /// are encouraged to do so.
  ///
  /// Instead of marking an element as hidden it should usually be excluded from
  /// the semantics tree altogether. Hidden elements are only included in the
  /// semantics tree to work around platform limitations and they are mainly
  /// used to implement accessibility scrolling on iOS.
  final bool? hidden;

  /// If non-null, whether [value] should be obscured.
  ///
  /// This option is usually set in combination with [textField] to indicate
  /// that the text field contains a password (or other sensitive information).
  /// Doing so instructs screen readers to not read out the [value].
  final bool? obscured;

  /// Whether the [value] is coming from a field that supports multiline text
  /// editing.
  ///
  /// This option is only meaningful when [textField] is true to indicate
  /// whether it's a single-line or multiline text field.
  ///
  /// This option is null when [textField] is false.
  final bool? multiline;

  /// If non-null, whether the node corresponds to the root of a subtree for
  /// which a route name should be announced.
  ///
  /// Generally, this is set in combination with
  /// [SemanticsConfiguration.explicitChildNodes], since nodes with this flag
  /// are not considered focusable by Android or iOS.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.scopesRoute] for a description of how the announced
  ///    value is selected.
  final bool? scopesRoute;

  /// If non-null, whether the node contains the semantic label for a route.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.namesRoute] for a description of how the name is used.
  final bool? namesRoute;

  /// If non-null, whether the node represents an image.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.isImage], for the flag this setting controls.
  final bool? image;

  /// If non-null, whether the node should be considered a live region.
  ///
  /// A live region indicates that updates to semantics node are important.
  /// Platforms may use this information to make polite announcements to the
  /// user to inform them of updates to this node.
  ///
  /// An example of a live region is a [SnackBar] widget. On Android and iOS,
  /// live region causes a polite announcement to be generated automatically,
  /// even if the widget does not have accessibility focus. This announcement
  /// may not be spoken if the OS accessibility services are already
  /// announcing something else, such as reading the label of a focused widget
  /// or providing a system announcement.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.isLiveRegion], the semantics flag this setting controls.
  ///  * [SemanticsConfiguration.liveRegion], for a full description of a live region.
  final bool? liveRegion;

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [textField] is true. Defaults to null,
  /// which means no limit is imposed on the text field.
  final int? maxValueLength;

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [textField] is true. Must be set when
  /// [maxValueLength] is set.
  final int? currentValueLength;

  /// Provides a textual description of the widget.
  ///
  /// If a label is provided, there must either by an ambient [Directionality]
  /// or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [label] and [attributedLabel]. One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.label] for a description of how this is exposed
  ///    in TalkBack and VoiceOver.
  ///  * [attributedLabel] for an [AttributedString] version of this property.
  final String? label;

  /// Provides an [AttributedString] version of textual description of the widget.
  ///
  /// If a [attributedLabel] is provided, there must either by an ambient
  /// [Directionality] or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [label] and [attributedLabel]. One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.attributedLabel] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  ///  * [label] for a plain string version of this property.
  final AttributedString? attributedLabel;

  /// Provides a textual description of the value of the widget.
  ///
  /// If a value is provided, there must either by an ambient [Directionality]
  /// or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [value] and [attributedValue], One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.value] for a description of how this is exposed
  ///    in TalkBack and VoiceOver.
  ///  * [attributedLabel] for an [AttributedString] version of this property.
  final String? value;

  /// Provides an [AttributedString] version of textual description of the value
  /// of the widget.
  ///
  /// If a [attributedValue] is provided, there must either by an ambient
  /// [Directionality] or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [value] and [attributedValue], One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.attributedValue] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  ///  * [value] for a plain string version of this property.
  final AttributedString? attributedValue;

  /// The value that [value] or [attributedValue] will become after a
  /// [SemanticsAction.increase] action has been performed on this widget.
  ///
  /// If a value is provided, [onIncrease] must also be set and there must
  /// either be an ambient [Directionality] or an explicit [textDirection]
  /// must be provided.
  ///
  /// Callers must not provide both [increasedValue] and
  /// [attributedIncreasedValue], One or both must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.increasedValue] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  ///  * [attributedIncreasedValue] for an [AttributedString] version of this
  ///    property.
  final String? increasedValue;

  /// The [AttributedString] that [value] or [attributedValue] will become after
  /// a [SemanticsAction.increase] action has been performed on this widget.
  ///
  /// If a [attributedIncreasedValue] is provided, [onIncrease] must also be set
  /// and there must either be an ambient [Directionality] or an explicit
  /// [textDirection] must be provided.
  ///
  /// Callers must not provide both [increasedValue] and
  /// [attributedIncreasedValue], One or both must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.attributedIncreasedValue] for a description of
  ///    how this is exposed in TalkBack and VoiceOver.
  ///  * [increasedValue] for a plain string version of this property.
  final AttributedString? attributedIncreasedValue;

  /// The value that [value] or [attributedValue] will become after a
  /// [SemanticsAction.decrease] action has been performed on this widget.
  ///
  /// If a value is provided, [onDecrease] must also be set and there must
  /// either be an ambient [Directionality] or an explicit [textDirection]
  /// must be provided.
  ///
  /// Callers must not provide both [decreasedValue] and
  /// [attributedDecreasedValue], One or both must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.decreasedValue] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  ///  * [attributedDecreasedValue] for an [AttributedString] version of this
  ///    property.
  final String? decreasedValue;

  /// The [AttributedString] that [value] or [attributedValue] will become after
  /// a [SemanticsAction.decrease] action has been performed on this widget.
  ///
  /// If a [attributedDecreasedValue] is provided, [onDecrease] must also be set
  /// and there must either be an ambient [Directionality] or an explicit
  /// [textDirection] must be provided.
  ///
  /// Callers must not provide both [decreasedValue] and
  /// [attributedDecreasedValue], One or both must be null/// provided.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.attributedDecreasedValue] for a description of
  ///    how this is exposed in TalkBack and VoiceOver.
  ///  * [decreasedValue] for a plain string version of this property.
  final AttributedString? attributedDecreasedValue;

  /// Provides a brief textual description of the result of an action performed
  /// on the widget.
  ///
  /// If a hint is provided, there must either be an ambient [Directionality]
  /// or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [hint] and [attributedHint], One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.hint] for a description of how this is exposed
  ///    in TalkBack and VoiceOver.
  ///  * [attributedHint] for an [AttributedString] version of this property.
  final String? hint;

  /// Provides an [AttributedString] version of brief textual description of the
  /// result of an action performed on the widget.
  ///
  /// If a [attributedHint] is provided, there must either by an ambient
  /// [Directionality] or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [hint] and [attributedHint], One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.attributedHint] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  ///  * [hint] for a plain string version of this property.
  final AttributedString? attributedHint;

  /// Provides a textual description of the widget's tooltip.
  ///
  /// In Android, this property sets the `AccessibilityNodeInfo.setTooltipText`.
  /// In iOS, this property is appended to the end of the
  /// `UIAccessibilityElement.accessibilityLabel`.
  ///
  /// If a [tooltip] is provided, there must either by an ambient
  /// [Directionality] or an explicit [textDirection] should be provided.
  final String? tooltip;

  /// Provides hint values which override the default hints on supported
  /// platforms.
  ///
  /// On Android, If no hint overrides are used then default [hint] will be
  /// combined with the [label]. Otherwise, the [hint] will be ignored as long
  /// as there as at least one non-null hint override.
  ///
  /// On iOS, these are always ignored and the default [hint] is used instead.
  final SemanticsHintOverrides? hintOverrides;

  /// The reading direction of the [label], [value], [increasedValue],
  /// [decreasedValue], and [hint].
  ///
  /// Defaults to the ambient [Directionality].
  final TextDirection? textDirection;

  /// Determines the position of this node among its siblings in the traversal
  /// sort order.
  ///
  /// This is used to describe the order in which the semantic node should be
  /// traversed by the accessibility services on the platform (e.g. VoiceOver
  /// on iOS and TalkBack on Android).
  final SemanticsSortKey? sortKey;

  /// A tag to be applied to the child [SemanticsNode]s of this widget.
  ///
  /// The tag is added to all child [SemanticsNode]s that pass through the
  /// [RenderObject] corresponding to this widget while looking to be attached
  /// to a parent SemanticsNode.
  ///
  /// Tags are used to communicate to a parent SemanticsNode that a child
  /// SemanticsNode was passed through a particular RenderObject. The parent can
  /// use this information to determine the shape of the semantics tree.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.addTagForChildren], to which the tags provided
  ///    here will be passed.
  final SemanticsTag? tagForChildren;

  /// The handler for [SemanticsAction.tap].
  ///
  /// This is the semantic equivalent of a user briefly tapping the screen with
  /// the finger without moving it. For example, a button should implement this
  /// action.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android *may* trigger this
  /// action by double-tapping the screen while an element is focused.
  ///
  /// Note: different OSes or assistive technologies may decide to interpret
  /// user inputs differently. Some may simulate real screen taps, while others
  /// may call semantics tap. One way to handle taps properly is to provide the
  /// same handler to both gesture tap and semantics tap.
  final VoidCallback? onTap;

  /// The handler for [SemanticsAction.longPress].
  ///
  /// This is the semantic equivalent of a user pressing and holding the screen
  /// with the finger for a few seconds without moving it.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android *may* trigger this
  /// action by double-tapping the screen without lifting the finger after the
  /// second tap.
  ///
  /// Note: different OSes or assistive technologies may decide to interpret
  /// user inputs differently. Some may simulate real long presses, while others
  /// may call semantics long press. One way to handle long press properly is to
  /// provide the same handler to both gesture long press and semantics long
  /// press.
  final VoidCallback? onLongPress;

  /// The handler for [SemanticsAction.scrollLeft].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from right to left. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping left with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback? onScrollLeft;

  /// The handler for [SemanticsAction.scrollRight].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from left to right. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping right with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback? onScrollRight;

  /// The handler for [SemanticsAction.scrollUp].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from bottom to top. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback? onScrollUp;

  /// The handler for [SemanticsAction.scrollDown].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from top to bottom. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback? onScrollDown;

  /// The handler for [SemanticsAction.increase].
  ///
  /// This is a request to increase the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If a [value] is set, [increasedValue] must also be provided and
  /// [onIncrease] must ensure that [value] will be set to [increasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume up button.
  final VoidCallback? onIncrease;

  /// The handler for [SemanticsAction.decrease].
  ///
  /// This is a request to decrease the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If a [value] is set, [decreasedValue] must also be provided and
  /// [onDecrease] must ensure that [value] will be set to [decreasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume down button.
  final VoidCallback? onDecrease;

  /// The handler for [SemanticsAction.copy].
  ///
  /// This is a request to copy the current selection to the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  final VoidCallback? onCopy;

  /// The handler for [SemanticsAction.cut].
  ///
  /// This is a request to cut the current selection and place it in the
  /// clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  final VoidCallback? onCut;

  /// The handler for [SemanticsAction.paste].
  ///
  /// This is a request to paste the current content of the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  final VoidCallback? onPaste;

  /// The handler for [SemanticsAction.moveCursorForwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field forward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume up key while the
  /// input focus is in a text field.
  final MoveCursorHandler? onMoveCursorForwardByCharacter;

  /// The handler for [SemanticsAction.moveCursorBackwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  final MoveCursorHandler? onMoveCursorBackwardByCharacter;

  /// The handler for [SemanticsAction.moveCursorForwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  final MoveCursorHandler? onMoveCursorForwardByWord;

  /// The handler for [SemanticsAction.moveCursorBackwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  final MoveCursorHandler? onMoveCursorBackwardByWord;

  /// The handler for [SemanticsAction.setSelection].
  ///
  /// This handler is invoked when the user either wants to change the currently
  /// selected text in a text field or change the position of the cursor.
  ///
  /// TalkBack users can trigger this handler by selecting "Move cursor to
  /// beginning/end" or "Select all" from the local context menu.
  final SetSelectionHandler? onSetSelection;

  /// The handler for [SemanticsAction.setText].
  ///
  /// This handler is invoked when the user wants to replace the current text in
  /// the text field with a new text.
  ///
  /// Voice access users can trigger this handler by speaking "type <text>" to
  /// their Android devices.
  final SetTextHandler? onSetText;

  /// The handler for [SemanticsAction.didGainAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler gains
  /// the accessibility focus. The accessibility focus is the
  /// green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidLoseAccessibilityFocus], which is invoked when the accessibility
  ///    focus is removed from the node.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  final VoidCallback? onDidGainAccessibilityFocus;

  /// The handler for [SemanticsAction.didLoseAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler
  /// loses the accessibility focus. The accessibility focus is
  /// the green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidGainAccessibilityFocus], which is invoked when the node gains
  ///    accessibility focus.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  final VoidCallback? onDidLoseAccessibilityFocus;

  /// The handler for [SemanticsAction.dismiss].
  ///
  /// This is a request to dismiss the currently focused node.
  ///
  /// TalkBack users on Android can trigger this action in the local context
  /// menu, and VoiceOver users on iOS can trigger this action with a standard
  /// gesture or menu option.
  final VoidCallback? onDismiss;

  /// A map from each supported [CustomSemanticsAction] to a provided handler.
  ///
  /// The handler associated with each custom action is called whenever a
  /// semantics action of type [SemanticsAction.customAction] is received. The
  /// provided argument will be an identifier used to retrieve an instance of
  /// a custom action which can then retrieve the correct handler from this map.
  ///
  /// See also:
  ///
  ///  * [CustomSemanticsAction], for an explanation of custom actions.
  final Map<CustomSemanticsAction, VoidCallback>? customSemanticsActions;

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<bool>('checked', checked, defaultValue: null));
    properties.add(DiagnosticsProperty<bool>('mixed', mixed, defaultValue: null));
    properties.add(DiagnosticsProperty<bool>('selected', selected, defaultValue: null));
    properties.add(StringProperty('label', label, defaultValue: null));
    properties.add(AttributedStringProperty('attributedLabel', attributedLabel, defaultValue: null));
    properties.add(StringProperty('value', value, defaultValue: null));
    properties.add(AttributedStringProperty('attributedValue', attributedValue, defaultValue: null));
    properties.add(StringProperty('increasedValue', value, defaultValue: null));
    properties.add(AttributedStringProperty('attributedIncreasedValue', attributedIncreasedValue, defaultValue: null));
    properties.add(StringProperty('decreasedValue', value, defaultValue: null));
    properties.add(AttributedStringProperty('attributedDecreasedValue', attributedDecreasedValue, defaultValue: null));
    properties.add(StringProperty('hint', hint, defaultValue: null));
    properties.add(AttributedStringProperty('attributedHint', attributedHint, defaultValue: null));
    properties.add(StringProperty('tooltip', tooltip));
    properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
    properties.add(DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null));
    properties.add(DiagnosticsProperty<SemanticsHintOverrides>('hintOverrides', hintOverrides, defaultValue: null));
  }

  @override
  String toStringShort() => objectRuntimeType(this, 'SemanticsProperties'); // the hashCode isn't important since we're immutable
}

/// In tests use this function to reset the counter used to generate
/// [SemanticsNode.id].
void debugResetSemanticsIdCounter() {
  SemanticsNode._lastIdentifier = 0;
}

/// A node that represents some semantic data.
///
/// The semantics tree is maintained during the semantics phase of the pipeline
/// (i.e., during [PipelineOwner.flushSemantics]), which happens after
/// compositing. The semantics tree is then uploaded into the engine for use
/// by assistive technology.
class SemanticsNode with DiagnosticableTreeMixin {
  /// Creates a semantic node.
  ///
  /// Each semantic node has a unique identifier that is assigned when the node
  /// is created.
  SemanticsNode({
    this.key,
    VoidCallback? showOnScreen,
  }) : _id = _generateNewId(),
       _showOnScreen = showOnScreen;

  /// Creates a semantic node to represent the root of the semantics tree.
  ///
  /// The root node is assigned an identifier of zero.
  SemanticsNode.root({
    this.key,
    VoidCallback? showOnScreen,
    required SemanticsOwner owner,
  }) : _id = 0,
       _showOnScreen = showOnScreen {
    attach(owner);
  }


  // The maximal semantic node identifier generated by the framework.
  //
  // The identifier range for semantic node IDs is split into 2, the least significant 16 bits are
  // reserved for framework generated IDs(generated with _generateNewId), and most significant 32
  // bits are reserved for engine generated IDs.
  static const int _maxFrameworkAccessibilityIdentifier = (1<<16) - 1;

  static int _lastIdentifier = 0;
  static int _generateNewId() {
    _lastIdentifier = (_lastIdentifier + 1) % _maxFrameworkAccessibilityIdentifier;
    return _lastIdentifier;
  }

  /// Uniquely identifies this node in the list of sibling nodes.
  ///
  /// Keys are used during the construction of the semantics tree. They are not
  /// transferred to the engine.
  final Key? key;

  /// The unique identifier for this node.
  ///
  /// The root node has an id of zero. Other nodes are given a unique id
  /// when they are attached to a [SemanticsOwner]. If they are detached, their
  /// ids are invalid and should not be used.
  ///
  /// In rare circumstances, id may change if this node is detached and
  /// re-attached to the [SemanticsOwner]. This should only happen when the
  /// application has generated too many semantics nodes.
  int get id => _id;
  int _id;

  final VoidCallback? _showOnScreen;

  // GEOMETRY

  /// The transform from this node's coordinate system to its parent's coordinate system.
  ///
  /// By default, the transform is null, which represents the identity
  /// transformation (i.e., that this node has the same coordinate system as its
  /// parent).
  Matrix4? get transform => _transform;
  Matrix4? _transform;
  set transform(Matrix4? value) {
    if (!MatrixUtils.matrixEquals(_transform, value)) {
      _transform = value == null || MatrixUtils.isIdentity(value) ? null : value;
      _markDirty();
    }
  }

  /// The bounding box for this node in its coordinate system.
  Rect get rect => _rect;
  Rect _rect = Rect.zero;
  set rect(Rect value) {
    assert(value.isFinite, '$this (with $owner) tried to set a non-finite rect.');
    if (_rect != value) {
      _rect = value;
      _markDirty();
    }
  }

  /// The semantic clip from an ancestor that was applied to this node.
  ///
  /// Expressed in the coordinate system of the node. May be null if no clip has
  /// been applied.
  ///
  /// Descendant [SemanticsNode]s that are positioned outside of this rect will
  /// be excluded from the semantics tree. Descendant [SemanticsNode]s that are
  /// overlapping with this rect, but are outside of [parentPaintClipRect] will
  /// be included in the tree, but they will be marked as hidden because they
  /// are assumed to be not visible on screen.
  ///
  /// If this rect is null, all descendant [SemanticsNode]s outside of
  /// [parentPaintClipRect] will be excluded from the tree.
  ///
  /// If this rect is non-null it has to completely enclose
  /// [parentPaintClipRect]. If [parentPaintClipRect] is null this property is
  /// also null.
  Rect? parentSemanticsClipRect;

  /// The paint clip from an ancestor that was applied to this node.
  ///
  /// Expressed in the coordinate system of the node. May be null if no clip has
  /// been applied.
  ///
  /// Descendant [SemanticsNode]s that are positioned outside of this rect will
  /// either be excluded from the semantics tree (if they have no overlap with
  /// [parentSemanticsClipRect]) or they will be included and marked as hidden
  /// (if they are overlapping with [parentSemanticsClipRect]).
  ///
  /// This rect is completely enclosed by [parentSemanticsClipRect].
  ///
  /// If this rect is null [parentSemanticsClipRect] also has to be null.
  Rect? parentPaintClipRect;

  /// The elevation adjustment that the parent imposes on this node.
  ///
  /// The [elevation] property is relative to the elevation of the parent
  /// [SemanticsNode]. However, as [SemanticsConfiguration]s from various
  /// ascending [RenderObject]s are merged into each other to form that
  /// [SemanticsNode] the parent’s elevation may change. This requires an
  /// adjustment of the child’s relative elevation which is represented by this
  /// value.
  ///
  /// The value is rarely accessed directly. Instead, for most use cases the
  /// [elevation] value should be used, which includes this adjustment.
  ///
  /// See also:
  ///
  ///  * [elevation], the actual elevation of this [SemanticsNode].
  double? elevationAdjustment;

  /// The index of this node within the parent's list of semantic children.
  ///
  /// This includes all semantic nodes, not just those currently in the
  /// child list. For example, if a scrollable has five children but the first
  /// two are not visible (and thus not included in the list of children), then
  /// the index of the last node will still be 4.
  int? indexInParent;

  /// Whether the node is invisible.
  ///
  /// A node whose [rect] is outside of the bounds of the screen and hence not
  /// reachable for users is considered invisible if its semantic information
  /// is not merged into a (partially) visible parent as indicated by
  /// [isMergedIntoParent].
  ///
  /// An invisible node can be safely dropped from the semantic tree without
  /// loosing semantic information that is relevant for describing the content
  /// currently shown on screen.
  bool get isInvisible => !isMergedIntoParent && rect.isEmpty;

  // MERGING

  /// Whether this node merges its semantic information into an ancestor node.
  bool get isMergedIntoParent => _isMergedIntoParent;
  bool _isMergedIntoParent = false;
  set isMergedIntoParent(bool value) {
    if (_isMergedIntoParent == value) {
      return;
    }
    _isMergedIntoParent = value;
    _markDirty();
  }

  /// Whether the user can interact with this node in assistive technologies.
  ///
  /// This node can still receive accessibility focus even if this is true.
  /// Setting this to true prevents the user from activating pointer related
  /// [SemanticsAction]s, such as [SemanticsAction.tap] or
  /// [SemanticsAction.longPress].
  bool get areUserActionsBlocked => _areUserActionsBlocked;
  bool _areUserActionsBlocked = false;
  set areUserActionsBlocked(bool value) {
    if (_areUserActionsBlocked == value) {
      return;
    }
    _areUserActionsBlocked = value;
    _markDirty();
  }

  /// Whether this node is taking part in a merge of semantic information.
  ///
  /// This returns true if the node is either merged into an ancestor node or if
  /// decedent nodes are merged into this node.
  ///
  /// See also:
  ///
  ///  * [isMergedIntoParent]
  ///  * [mergeAllDescendantsIntoThisNode]
  bool get isPartOfNodeMerging => mergeAllDescendantsIntoThisNode || isMergedIntoParent;

  /// Whether this node and all of its descendants should be treated as one logical entity.
  bool get mergeAllDescendantsIntoThisNode => _mergeAllDescendantsIntoThisNode;
  bool _mergeAllDescendantsIntoThisNode = _kEmptyConfig.isMergingSemanticsOfDescendants;


  // CHILDREN

  /// Contains the children in inverse hit test order (i.e. paint order).
  List<SemanticsNode>? _children;

  /// A snapshot of `newChildren` passed to [_replaceChildren] that we keep in
  /// debug mode. It supports the assertion that user does not mutate the list
  /// of children.
  late List<SemanticsNode> _debugPreviousSnapshot;

  void _replaceChildren(List<SemanticsNode> newChildren) {
    assert(!newChildren.any((SemanticsNode child) => child == this));
    assert(() {
      if (identical(newChildren, _children)) {
        final List<DiagnosticsNode> mutationErrors = <DiagnosticsNode>[];
        if (newChildren.length != _debugPreviousSnapshot.length) {
          mutationErrors.add(ErrorDescription(
            "The list's length has changed from ${_debugPreviousSnapshot.length} "
            'to ${newChildren.length}.',
          ));
        } else {
          for (int i = 0; i < newChildren.length; i++) {
            if (!identical(newChildren[i], _debugPreviousSnapshot[i])) {
              if (mutationErrors.isNotEmpty) {
                mutationErrors.add(ErrorSpacer());
              }
              mutationErrors.add(ErrorDescription('Child node at position $i was replaced:'));
              mutationErrors.add(newChildren[i].toDiagnosticsNode(name: 'Previous child', style: DiagnosticsTreeStyle.singleLine));
              mutationErrors.add(_debugPreviousSnapshot[i].toDiagnosticsNode(name: 'New child', style: DiagnosticsTreeStyle.singleLine));
            }
          }
        }
        if (mutationErrors.isNotEmpty) {
          throw FlutterError.fromParts(<DiagnosticsNode>[
            ErrorSummary('Failed to replace child semantics nodes because the list of `SemanticsNode`s was mutated.'),
            ErrorHint('Instead of mutating the existing list, create a new list containing the desired `SemanticsNode`s.'),
            ErrorDescription('Error details:'),
            ...mutationErrors,
          ]);
        }
      }
      assert(!newChildren.any((SemanticsNode node) => node.isMergedIntoParent) || isPartOfNodeMerging);

      _debugPreviousSnapshot = List<SemanticsNode>.of(newChildren);

      SemanticsNode ancestor = this;
      while (ancestor.parent is SemanticsNode) {
        ancestor = ancestor.parent!;
      }
      assert(!newChildren.any((SemanticsNode child) => child == ancestor));
      return true;
    }());
    assert(() {
      final Set<SemanticsNode> seenChildren = <SemanticsNode>{};
      for (final SemanticsNode child in newChildren) {
        assert(seenChildren.add(child));
      } // check for duplicate adds
      return true;
    }());

    // The goal of this function is updating sawChange.
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        child._dead = true;
      }
    }
    for (final SemanticsNode child in newChildren) {
      assert(!child.isInvisible, 'Child $child is invisible and should not be added as a child of $this.');
      child._dead = false;
    }
    bool sawChange = false;
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        if (child._dead) {
          if (child.parent == this) {
            // we might have already had our child stolen from us by
            // another node that is deeper in the tree.
            _dropChild(child);
          }
          sawChange = true;
        }
      }
    }
    for (final SemanticsNode child in newChildren) {
      if (child.parent != this) {
        if (child.parent != null) {
          // we're rebuilding the tree from the bottom up, so it's possible
          // that our child was, in the last pass, a child of one of our
          // ancestors. In that case, we drop the child eagerly here.
          // TODO(ianh): Find a way to assert that the same node didn't
          // actually appear in the tree in two places.
          child.parent?._dropChild(child);
        }
        assert(!child.attached);
        _adoptChild(child);
        sawChange = true;
      }
    }
    if (!sawChange && _children != null) {
      assert(newChildren.length == _children!.length);
      // Did the order change?
      for (int i = 0; i < _children!.length; i++) {
        if (_children![i].id != newChildren[i].id) {
          sawChange = true;
          break;
        }
      }
    }
    _children = newChildren;
    if (sawChange) {
      _markDirty();
    }
  }

  /// Whether this node has a non-zero number of children.
  bool get hasChildren => _children?.isNotEmpty ?? false;
  bool _dead = false;

  /// The number of children this node has.
  int get childrenCount => hasChildren ? _children!.length : 0;

  /// Visits the immediate children of this node.
  ///
  /// This function calls visitor for each immediate child until visitor returns
  /// false. Returns true if all the visitor calls returned true, otherwise
  /// returns false.
  void visitChildren(SemanticsNodeVisitor visitor) {
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        if (!visitor(child)) {
          return;
        }
      }
    }
  }

  /// Visit all the descendants of this node.
  ///
  /// This function calls visitor for each descendant in a pre-order traversal
  /// until visitor returns false. Returns true if all the visitor calls
  /// returned true, otherwise returns false.
  bool _visitDescendants(SemanticsNodeVisitor visitor) {
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        if (!visitor(child) || !child._visitDescendants(visitor)) {
          return false;
        }
      }
    }
    return true;
  }

  /// The owner for this node (null if unattached).
  ///
  /// The entire subtree that this node belongs to will have the same owner.
  SemanticsOwner? get owner => _owner;
  SemanticsOwner? _owner;

  /// Whether this node is in a tree whose root is attached to something.
  ///
  /// This becomes true during the call to [attach].
  ///
  /// This becomes false during the call to [detach].
  bool get attached => _owner != null;

  /// The parent of this node in the tree.
  SemanticsNode? get parent => _parent;
  SemanticsNode? _parent;

  /// The depth of this node in the tree.
  ///
  /// The depth of nodes in a tree monotonically increases as you traverse down
  /// the tree.
  int get depth => _depth;
  int _depth = 0;

  void _redepthChild(SemanticsNode child) {
    assert(child.owner == owner);
    if (child._depth <= _depth) {
      child._depth = _depth + 1;
      child._redepthChildren();
    }
  }

  void _redepthChildren() {
    _children?.forEach(_redepthChild);
  }

  void _adoptChild(SemanticsNode child) {
    assert(child._parent == null);
    assert(() {
      SemanticsNode node = this;
      while (node.parent != null) {
        node = node.parent!;
      }
      assert(node != child); // indicates we are about to create a cycle
      return true;
    }());
    child._parent = this;
    if (attached) {
      child.attach(_owner!);
    }
    _redepthChild(child);
  }

  void _dropChild(SemanticsNode child) {
    assert(child._parent == this);
    assert(child.attached == attached);
    child._parent = null;
    if (attached) {
      child.detach();
    }
  }

  /// Mark this node as attached to the given owner.
  @visibleForTesting
  void attach(SemanticsOwner owner) {
    assert(_owner == null);
    _owner = owner;
    while (owner._nodes.containsKey(id)) {
      // Ids may repeat if the Flutter has generated > 2^16 ids. We need to keep
      // regenerating the id until we found an id that is not used.
      _id = _generateNewId();
    }
    owner._nodes[id] = this;
    owner._detachedNodes.remove(this);
    if (_dirty) {
      _dirty = false;
      _markDirty();
    }
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        child.attach(owner);
      }
    }
  }

  /// Mark this node as detached.
  @visibleForTesting
  void detach() {
    assert(_owner != null);
    assert(owner!._nodes.containsKey(id));
    assert(!owner!._detachedNodes.contains(this));
    owner!._nodes.remove(id);
    owner!._detachedNodes.add(this);
    _owner = null;
    assert(parent == null || attached == parent!.attached);
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        // The list of children may be stale and may contain nodes that have
        // been assigned to a different parent.
        if (child.parent == this) {
          child.detach();
        }
      }
    }
    // The other side will have forgotten this node if we ever send
    // it again, so make sure to mark it dirty so that it'll get
    // sent if it is resurrected.
    _markDirty();
  }

  // DIRTY MANAGEMENT

  bool _dirty = false;
  void _markDirty() {
    if (_dirty) {
      return;
    }
    _dirty = true;
    if (attached) {
      assert(!owner!._detachedNodes.contains(this));
      owner!._dirtyNodes.add(this);
    }
  }

  bool _isDifferentFromCurrentSemanticAnnotation(SemanticsConfiguration config) {
    return _attributedLabel != config.attributedLabel
        || _attributedHint != config.attributedHint
        || _elevation != config.elevation
        || _thickness != config.thickness
        || _attributedValue != config.attributedValue
        || _attributedIncreasedValue != config.attributedIncreasedValue
        || _attributedDecreasedValue != config.attributedDecreasedValue
        || _tooltip != config.tooltip
        || _flags != config._flags
        || _textDirection != config.textDirection
        || _sortKey != config._sortKey
        || _textSelection != config._textSelection
        || _scrollPosition != config._scrollPosition
        || _scrollExtentMax != config._scrollExtentMax
        || _scrollExtentMin != config._scrollExtentMin
        || _actionsAsBits != config._actionsAsBits
        || indexInParent != config.indexInParent
        || platformViewId != config.platformViewId
        || _maxValueLength != config._maxValueLength
        || _currentValueLength != config._currentValueLength
        || _mergeAllDescendantsIntoThisNode != config.isMergingSemanticsOfDescendants
        || _areUserActionsBlocked != config.isBlockingUserActions;
  }

  // TAGS, LABELS, ACTIONS

  Map<SemanticsAction, SemanticsActionHandler> _actions = _kEmptyConfig._actions;
  Map<CustomSemanticsAction, VoidCallback> _customSemanticsActions = _kEmptyConfig._customSemanticsActions;

  int get _effectiveActionsAsBits => _areUserActionsBlocked ? _actionsAsBits & _kUnblockedUserActions : _actionsAsBits;
  int _actionsAsBits = _kEmptyConfig._actionsAsBits;

  /// The [SemanticsTag]s this node is tagged with.
  ///
  /// Tags are used during the construction of the semantics tree. They are not
  /// transferred to the engine.
  Set<SemanticsTag>? tags;

  /// Whether this node is tagged with `tag`.
  bool isTagged(SemanticsTag tag) => tags != null && tags!.contains(tag);

  int _flags = _kEmptyConfig._flags;

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

  /// A textual description of this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedLabel].
  String get label => _attributedLabel.string;

  /// A textual description of this node in [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [label], which exposes just the raw text.
  AttributedString get attributedLabel => _attributedLabel;
  AttributedString _attributedLabel = _kEmptyConfig.attributedLabel;

  /// A textual description for the current value of the node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedValue].
  String get value => _attributedValue.string;

  /// A textual description for the current value of the node in
  /// [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [value], which exposes just the raw text.
  AttributedString get attributedValue => _attributedValue;
  AttributedString _attributedValue = _kEmptyConfig.attributedValue;

  /// The value that [value] will have after a [SemanticsAction.increase] action
  /// has been performed.
  ///
  /// This property is only valid if the [SemanticsAction.increase] action is
  /// available on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedIncreasedValue].
  String get increasedValue => _attributedIncreasedValue.string;

  /// The value in [AttributedString] format that [value] or [attributedValue]
  /// will have after a [SemanticsAction.increase] action has been performed.
  ///
  /// This property is only valid if the [SemanticsAction.increase] action is
  /// available on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [increasedValue], which exposes just the raw text.
  AttributedString get attributedIncreasedValue => _attributedIncreasedValue;
  AttributedString _attributedIncreasedValue = _kEmptyConfig.attributedIncreasedValue;

  /// The value that [value] will have after a [SemanticsAction.decrease] action
  /// has been performed.
  ///
  /// This property is only valid if the [SemanticsAction.decrease] action is
  /// available on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedDecreasedValue].
  String get decreasedValue => _attributedDecreasedValue.string;

  /// The value in [AttributedString] format that [value] or [attributedValue]
  /// will have after a [SemanticsAction.decrease] action has been performed.
  ///
  /// This property is only valid if the [SemanticsAction.decrease] action is
  /// available on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [decreasedValue], which exposes just the raw text.
  AttributedString get attributedDecreasedValue => _attributedDecreasedValue;
  AttributedString _attributedDecreasedValue = _kEmptyConfig.attributedDecreasedValue;

  /// A brief description of the result of performing an action on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedHint].
  String get hint => _attributedHint.string;

  /// A brief description of the result of performing an action on this node
  /// in [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [hint], which exposes just the raw text.
  AttributedString get attributedHint => _attributedHint;
  AttributedString _attributedHint = _kEmptyConfig.attributedHint;

  /// A textual description of the widget's tooltip.
  ///
  /// The reading direction is given by [textDirection].
  String get tooltip => _tooltip;
  String _tooltip = _kEmptyConfig.tooltip;

  /// The elevation along the z-axis at which the [rect] of this [SemanticsNode]
  /// is located above its parent.
  ///
  /// The value is relative to the parent's [elevation]. The sum of the
  /// [elevation]s of all ancestor node plus this value determines the absolute
  /// elevation of this [SemanticsNode].
  ///
  /// See also:
  ///
  ///  * [thickness], which describes how much space in z-direction this
  ///    [SemanticsNode] occupies starting at this [elevation].
  ///  * [elevationAdjustment], which has been used to calculate this value.
  double get elevation => _elevation;
  double _elevation = _kEmptyConfig.elevation;

  /// Describes how much space the [SemanticsNode] takes up along the z-axis.
  ///
  /// A [SemanticsNode] represents multiple [RenderObject]s, which can be
  /// located at various elevations in 3D. The [thickness] is the difference
  /// between the absolute elevations of the lowest and highest [RenderObject]
  /// represented by this [SemanticsNode]. In other words, the thickness
  /// describes how high the box is that this [SemanticsNode] occupies in three
  /// dimensional space. The two other dimensions are defined by [rect].
  ///
  /// {@tool snippet}
  /// The following code stacks three [PhysicalModel]s on top of each other
  /// separated by non-zero elevations.
  ///
  /// [PhysicalModel] C is elevated 10.0 above [PhysicalModel] B, which in turn
  /// is elevated 5.0 above [PhysicalModel] A. The side view of this
  /// constellation looks as follows:
  ///
  /// ![A diagram illustrating the elevations of three PhysicalModels and their
  /// corresponding SemanticsNodes.](https://flutter.github.io/assets-for-api-docs/assets/semantics/SemanticsNode.thickness.png)
  ///
  /// In this example the [RenderObject]s for [PhysicalModel] C and B share one
  /// [SemanticsNode] Y. Given the elevations of those [RenderObject]s, this
  /// [SemanticsNode] has a [thickness] of 10.0 and an elevation of 5.0 over
  /// its parent [SemanticsNode] X.
  /// ```dart
  /// PhysicalModel( // A
  ///   color: Colors.amber,
  ///   child: Semantics(
  ///     explicitChildNodes: true,
  ///     child: const PhysicalModel( // B
  ///       color: Colors.brown,
  ///       elevation: 5.0,
  ///       child: PhysicalModel( // C
  ///         color: Colors.cyan,
  ///         elevation: 10.0,
  ///         child: Placeholder(),
  ///       ),
  ///     ),
  ///   ),
  /// )
  /// ```
  /// {@end-tool}
  ///
  /// See also:
  ///
  ///  * [elevation], which describes the elevation of the box defined by
  ///    [thickness] and [rect] relative to the parent of this [SemanticsNode].
  double get thickness => _thickness;
  double _thickness = _kEmptyConfig.thickness;

  /// Provides hint values which override the default hints on supported
  /// platforms.
  SemanticsHintOverrides? get hintOverrides => _hintOverrides;
  SemanticsHintOverrides? _hintOverrides;

  /// The reading direction for [label], [value], [hint], [increasedValue], and
  /// [decreasedValue].
  TextDirection? get textDirection => _textDirection;
  TextDirection? _textDirection = _kEmptyConfig.textDirection;

  /// Determines the position of this node among its siblings in the traversal
  /// sort order.
  ///
  /// This is used to describe the order in which the semantic node should be
  /// traversed by the accessibility services on the platform (e.g. VoiceOver
  /// on iOS and TalkBack on Android).
  SemanticsSortKey? get sortKey => _sortKey;
  SemanticsSortKey? _sortKey;

  /// The currently selected text (or the position of the cursor) within [value]
  /// if this node represents a text field.
  TextSelection? get textSelection => _textSelection;
  TextSelection? _textSelection;

  /// If this node represents a text field, this indicates whether or not it's
  /// a multiline text field.
  bool? get isMultiline => _isMultiline;
  bool? _isMultiline;

  /// The total number of scrollable children that contribute to semantics.
  ///
  /// If the number of children are unknown or unbounded, this value will be
  /// null.
  int? get scrollChildCount => _scrollChildCount;
  int? _scrollChildCount;

  /// The index of the first visible semantic child of a scroll node.
  int? get scrollIndex => _scrollIndex;
  int? _scrollIndex;

  /// Indicates the current scrolling position in logical pixels if the node is
  /// scrollable.
  ///
  /// The properties [scrollExtentMin] and [scrollExtentMax] indicate the valid
  /// in-range values for this property. The value for [scrollPosition] may
  /// (temporarily) be outside that range, e.g. during an overscroll.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.pixels], from where this value is usually taken.
  double? get scrollPosition => _scrollPosition;
  double? _scrollPosition;

  /// Indicates the maximum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.maxScrollExtent], from where this value is usually taken.
  double? get scrollExtentMax => _scrollExtentMax;
  double? _scrollExtentMax;

  /// Indicates the minimum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.minScrollExtent] from where this value is usually taken.
  double? get scrollExtentMin => _scrollExtentMin;
  double? _scrollExtentMin;

  /// The id of the platform view, whose semantics nodes will be added as
  /// children to this node.
  ///
  /// If this value is non-null, the SemanticsNode must not have any children
  /// as those would be replaced by the semantics nodes of the referenced
  /// platform view.
  ///
  /// See also:
  ///
  ///  * [AndroidView], which is the platform view for Android.
  ///  * [UiKitView], which is the platform view for iOS.
  int? get platformViewId => _platformViewId;
  int? _platformViewId;

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. Defaults
  /// to null, which means no limit is imposed on the text field.
  int? get maxValueLength => _maxValueLength;
  int? _maxValueLength;

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. Must be
  /// set when [maxValueLength] is set.
  int? get currentValueLength => _currentValueLength;
  int? _currentValueLength;

  bool _canPerformAction(SemanticsAction action) => _actions.containsKey(action);

  static final SemanticsConfiguration _kEmptyConfig = SemanticsConfiguration();

  /// Reconfigures the properties of this object to describe the configuration
  /// provided in the `config` argument and the children listed in the
  /// `childrenInInversePaintOrder` argument.
  ///
  /// The arguments may be null; this represents an empty configuration (all
  /// values at their defaults, no children).
  ///
  /// No reference is kept to the [SemanticsConfiguration] object, but the child
  /// list is used as-is and should therefore not be changed after this call.
  void updateWith({
    required SemanticsConfiguration? config,
    List<SemanticsNode>? childrenInInversePaintOrder,
  }) {
    config ??= _kEmptyConfig;
    if (_isDifferentFromCurrentSemanticAnnotation(config)) {
      _markDirty();
    }

    assert(
      config.platformViewId == null || childrenInInversePaintOrder == null || childrenInInversePaintOrder.isEmpty,
      'SemanticsNodes with children must not specify a platformViewId.',
    );

    _attributedLabel = config.attributedLabel;
    _attributedValue = config.attributedValue;
    _attributedIncreasedValue = config.attributedIncreasedValue;
    _attributedDecreasedValue = config.attributedDecreasedValue;
    _attributedHint = config.attributedHint;
    _tooltip = config.tooltip;
    _hintOverrides = config.hintOverrides;
    _elevation = config.elevation;
    _thickness = config.thickness;
    _flags = config._flags;
    _textDirection = config.textDirection;
    _sortKey = config.sortKey;
    _actions = Map<SemanticsAction, SemanticsActionHandler>.of(config._actions);
    _customSemanticsActions = Map<CustomSemanticsAction, VoidCallback>.of(config._customSemanticsActions);
    _actionsAsBits = config._actionsAsBits;
    _textSelection = config._textSelection;
    _isMultiline = config.isMultiline;
    _scrollPosition = config._scrollPosition;
    _scrollExtentMax = config._scrollExtentMax;
    _scrollExtentMin = config._scrollExtentMin;
    _mergeAllDescendantsIntoThisNode = config.isMergingSemanticsOfDescendants;
    _scrollChildCount = config.scrollChildCount;
    _scrollIndex = config.scrollIndex;
    indexInParent = config.indexInParent;
    _platformViewId = config._platformViewId;
    _maxValueLength = config._maxValueLength;
    _currentValueLength = config._currentValueLength;
    _areUserActionsBlocked = config.isBlockingUserActions;
    _replaceChildren(childrenInInversePaintOrder ?? const <SemanticsNode>[]);

    assert(
      !_canPerformAction(SemanticsAction.increase) || (value == '') == (increasedValue == ''),
      'A SemanticsNode with action "increase" needs to be annotated with either both "value" and "increasedValue" or neither',
    );
    assert(
      !_canPerformAction(SemanticsAction.decrease) || (value == '') == (decreasedValue == ''),
      'A SemanticsNode with action "decrease" needs to be annotated with either both "value" and "decreasedValue" or neither',
    );
  }


  /// Returns a summary of the semantics for this node.
  ///
  /// If this node has [mergeAllDescendantsIntoThisNode], then the returned data
  /// includes the information from this node's descendants. Otherwise, the
  /// returned data matches the data on this node.
  SemanticsData getSemanticsData() {
    int flags = _flags;
    // Can't use _effectiveActionsAsBits here. The filtering of action bits
    // must be done after the merging the its descendants.
    int actions = _actionsAsBits;
    AttributedString attributedLabel = _attributedLabel;
    AttributedString attributedValue = _attributedValue;
    AttributedString attributedIncreasedValue = _attributedIncreasedValue;
    AttributedString attributedDecreasedValue = _attributedDecreasedValue;
    AttributedString attributedHint = _attributedHint;
    String tooltip = _tooltip;
    TextDirection? textDirection = _textDirection;
    Set<SemanticsTag>? mergedTags = tags == null ? null : Set<SemanticsTag>.of(tags!);
    TextSelection? textSelection = _textSelection;
    int? scrollChildCount = _scrollChildCount;
    int? scrollIndex = _scrollIndex;
    double? scrollPosition = _scrollPosition;
    double? scrollExtentMax = _scrollExtentMax;
    double? scrollExtentMin = _scrollExtentMin;
    int? platformViewId = _platformViewId;
    int? maxValueLength = _maxValueLength;
    int? currentValueLength = _currentValueLength;
    final double elevation = _elevation;
    double thickness = _thickness;
    final Set<int> customSemanticsActionIds = <int>{};
    for (final CustomSemanticsAction action in _customSemanticsActions.keys) {
      customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
    }
    if (hintOverrides != null) {
      if (hintOverrides!.onTapHint != null) {
        final CustomSemanticsAction action = CustomSemanticsAction.overridingAction(
          hint: hintOverrides!.onTapHint!,
          action: SemanticsAction.tap,
        );
        customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
      }
      if (hintOverrides!.onLongPressHint != null) {
        final CustomSemanticsAction action = CustomSemanticsAction.overridingAction(
          hint: hintOverrides!.onLongPressHint!,
          action: SemanticsAction.longPress,
        );
        customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
      }
    }

    if (mergeAllDescendantsIntoThisNode) {
      _visitDescendants((SemanticsNode node) {
        assert(node.isMergedIntoParent);
        flags |= node._flags;
        actions |= node._effectiveActionsAsBits;

        textDirection ??= node._textDirection;
        textSelection ??= node._textSelection;
        scrollChildCount ??= node._scrollChildCount;
        scrollIndex ??= node._scrollIndex;
        scrollPosition ??= node._scrollPosition;
        scrollExtentMax ??= node._scrollExtentMax;
        scrollExtentMin ??= node._scrollExtentMin;
        platformViewId ??= node._platformViewId;
        maxValueLength ??= node._maxValueLength;
        currentValueLength ??= node._currentValueLength;
        if (attributedValue.string == '') {
          attributedValue = node._attributedValue;
        }
        if (attributedIncreasedValue.string == '') {
          attributedIncreasedValue = node._attributedIncreasedValue;
        }
        if (attributedDecreasedValue.string == '') {
          attributedDecreasedValue = node._attributedDecreasedValue;
        }
        if (tooltip == '') {
          tooltip = node._tooltip;
        }
        if (node.tags != null) {
          mergedTags ??= <SemanticsTag>{};
          mergedTags!.addAll(node.tags!);
        }
        for (final CustomSemanticsAction action in _customSemanticsActions.keys) {
          customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
        }
        if (node.hintOverrides != null) {
          if (node.hintOverrides!.onTapHint != null) {
            final CustomSemanticsAction action = CustomSemanticsAction.overridingAction(
              hint: node.hintOverrides!.onTapHint!,
              action: SemanticsAction.tap,
            );
            customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
          }
          if (node.hintOverrides!.onLongPressHint != null) {
            final CustomSemanticsAction action = CustomSemanticsAction.overridingAction(
              hint: node.hintOverrides!.onLongPressHint!,
              action: SemanticsAction.longPress,
            );
            customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
          }
        }
        attributedLabel = _concatAttributedString(
          thisAttributedString: attributedLabel,
          thisTextDirection: textDirection,
          otherAttributedString: node._attributedLabel,
          otherTextDirection: node._textDirection,
        );
        attributedHint = _concatAttributedString(
          thisAttributedString: attributedHint,
          thisTextDirection: textDirection,
          otherAttributedString: node._attributedHint,
          otherTextDirection: node._textDirection,
        );

        thickness = math.max(thickness, node._thickness + node._elevation);

        return true;
      });
    }

    return SemanticsData(
      flags: flags,
      actions: _areUserActionsBlocked ? actions & _kUnblockedUserActions : actions,
      attributedLabel: attributedLabel,
      attributedValue: attributedValue,
      attributedIncreasedValue: attributedIncreasedValue,
      attributedDecreasedValue: attributedDecreasedValue,
      attributedHint: attributedHint,
      tooltip: tooltip,
      textDirection: textDirection,
      rect: rect,
      transform: transform,
      elevation: elevation,
      thickness: thickness,
      tags: mergedTags,
      textSelection: textSelection,
      scrollChildCount: scrollChildCount,
      scrollIndex: scrollIndex,
      scrollPosition: scrollPosition,
      scrollExtentMax: scrollExtentMax,
      scrollExtentMin: scrollExtentMin,
      platformViewId: platformViewId,
      maxValueLength: maxValueLength,
      currentValueLength: currentValueLength,
      customSemanticsActionIds: customSemanticsActionIds.toList()..sort(),
    );
  }

  static Float64List _initIdentityTransform() {
    return Matrix4.identity().storage;
  }

  static final Int32List _kEmptyChildList = Int32List(0);
  static final Int32List _kEmptyCustomSemanticsActionsList = Int32List(0);
  static final Float64List _kIdentityTransform = _initIdentityTransform();

  void _addToUpdate(SemanticsUpdateBuilder builder, Set<int> customSemanticsActionIdsUpdate) {
    assert(_dirty);
    final SemanticsData data = getSemanticsData();
    final Int32List childrenInTraversalOrder;
    final Int32List childrenInHitTestOrder;
    if (!hasChildren || mergeAllDescendantsIntoThisNode) {
      childrenInTraversalOrder = _kEmptyChildList;
      childrenInHitTestOrder = _kEmptyChildList;
    } else {
      final int childCount = _children!.length;
      final List<SemanticsNode> sortedChildren = _childrenInTraversalOrder();
      childrenInTraversalOrder = Int32List(childCount);
      for (int i = 0; i < childCount; i += 1) {
        childrenInTraversalOrder[i] = sortedChildren[i].id;
      }
      // _children is sorted in paint order, so we invert it to get the hit test
      // order.
      childrenInHitTestOrder = Int32List(childCount);
      for (int i = childCount - 1; i >= 0; i -= 1) {
        childrenInHitTestOrder[i] = _children![childCount - i - 1].id;
      }
    }
    Int32List? customSemanticsActionIds;
    if (data.customSemanticsActionIds?.isNotEmpty ?? false) {
      customSemanticsActionIds = Int32List(data.customSemanticsActionIds!.length);
      for (int i = 0; i < data.customSemanticsActionIds!.length; i++) {
        customSemanticsActionIds[i] = data.customSemanticsActionIds![i];
        customSemanticsActionIdsUpdate.add(data.customSemanticsActionIds![i]);
      }
    }
    builder.updateNode(
      id: id,
      flags: data.flags,
      actions: data.actions,
      rect: data.rect,
      label: data.attributedLabel.string,
      labelAttributes: data.attributedLabel.attributes,
      value: data.attributedValue.string,
      valueAttributes: data.attributedValue.attributes,
      increasedValue: data.attributedIncreasedValue.string,
      increasedValueAttributes: data.attributedIncreasedValue.attributes,
      decreasedValue: data.attributedDecreasedValue.string,
      decreasedValueAttributes: data.attributedDecreasedValue.attributes,
      hint: data.attributedHint.string,
      hintAttributes: data.attributedHint.attributes,
      tooltip: data.tooltip,
      textDirection: data.textDirection,
      textSelectionBase: data.textSelection != null ? data.textSelection!.baseOffset : -1,
      textSelectionExtent: data.textSelection != null ? data.textSelection!.extentOffset : -1,
      platformViewId: data.platformViewId ?? -1,
      maxValueLength: data.maxValueLength ?? -1,
      currentValueLength: data.currentValueLength ?? -1,
      scrollChildren: data.scrollChildCount ?? 0,
      scrollIndex: data.scrollIndex ?? 0 ,
      scrollPosition: data.scrollPosition ?? double.nan,
      scrollExtentMax: data.scrollExtentMax ?? double.nan,
      scrollExtentMin: data.scrollExtentMin ?? double.nan,
      transform: data.transform?.storage ?? _kIdentityTransform,
      elevation: data.elevation,
      thickness: data.thickness,
      childrenInTraversalOrder: childrenInTraversalOrder,
      childrenInHitTestOrder: childrenInHitTestOrder,
      additionalActions: customSemanticsActionIds ?? _kEmptyCustomSemanticsActionsList,
    );
    _dirty = false;
  }

  /// Builds a new list made of [_children] sorted in semantic traversal order.
  List<SemanticsNode> _childrenInTraversalOrder() {
    TextDirection? inheritedTextDirection = textDirection;
    SemanticsNode? ancestor = parent;
    while (inheritedTextDirection == null && ancestor != null) {
      inheritedTextDirection = ancestor.textDirection;
      ancestor = ancestor.parent;
    }

    List<SemanticsNode>? childrenInDefaultOrder;
    if (inheritedTextDirection != null) {
      childrenInDefaultOrder = _childrenInDefaultOrder(_children!, inheritedTextDirection);
    } else {
      // In the absence of text direction default to paint order.
      childrenInDefaultOrder = _children;
    }

    // List.sort does not guarantee stable sort order. Therefore, children are
    // first partitioned into groups that have compatible sort keys, i.e. keys
    // in the same group can be compared to each other. These groups stay in
    // the same place. Only children within the same group are sorted.
    final List<_TraversalSortNode> everythingSorted = <_TraversalSortNode>[];
    final List<_TraversalSortNode> sortNodes = <_TraversalSortNode>[];
    SemanticsSortKey? lastSortKey;
    for (int position = 0; position < childrenInDefaultOrder!.length; position += 1) {
      final SemanticsNode child = childrenInDefaultOrder[position];
      final SemanticsSortKey? sortKey = child.sortKey;
      lastSortKey = position > 0
          ? childrenInDefaultOrder[position - 1].sortKey
          : null;
      final bool isCompatibleWithPreviousSortKey = position == 0 ||
          sortKey.runtimeType == lastSortKey.runtimeType &&
          (sortKey == null || sortKey.name == lastSortKey!.name);
      if (!isCompatibleWithPreviousSortKey && sortNodes.isNotEmpty) {
        // Do not sort groups with null sort keys. List.sort does not guarantee
        // a stable sort order.
        if (lastSortKey != null) {
          sortNodes.sort();
        }
        everythingSorted.addAll(sortNodes);
        sortNodes.clear();
      }

      sortNodes.add(_TraversalSortNode(
        node: child,
        sortKey: sortKey,
        position: position,
      ));
    }

    // Do not sort groups with null sort keys. List.sort does not guarantee
    // a stable sort order.
    if (lastSortKey != null) {
      sortNodes.sort();
    }
    everythingSorted.addAll(sortNodes);

    return everythingSorted
      .map<SemanticsNode>((_TraversalSortNode sortNode) => sortNode.node)
      .toList();
  }

  /// Sends a [SemanticsEvent] associated with this [SemanticsNode].
  ///
  /// Semantics events should be sent to inform interested parties (like
  /// the accessibility system of the operating system) about changes to the UI.
  void sendEvent(SemanticsEvent event) {
    if (!attached) {
      return;
    }
    SystemChannels.accessibility.send(event.toMap(nodeId: id));
  }

  bool _debugIsActionBlocked(SemanticsAction action) {
    bool result = false;
    assert((){
      result = (_effectiveActionsAsBits & action.index) == 0;
      return true;
    }());
    return result;
  }

  @override
  String toStringShort() => '${objectRuntimeType(this, 'SemanticsNode')}#$id';

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    bool hideOwner = true;
    if (_dirty) {
      final bool inDirtyNodes = owner != null && owner!._dirtyNodes.contains(this);
      properties.add(FlagProperty('inDirtyNodes', value: inDirtyNodes, ifTrue: 'dirty', ifFalse: 'STALE'));
      hideOwner = inDirtyNodes;
    }
    properties.add(DiagnosticsProperty<SemanticsOwner>('owner', owner, level: hideOwner ? DiagnosticLevel.hidden : DiagnosticLevel.info));
    properties.add(FlagProperty('isMergedIntoParent', value: isMergedIntoParent, ifTrue: 'merged up ⬆️'));
    properties.add(FlagProperty('mergeAllDescendantsIntoThisNode', value: mergeAllDescendantsIntoThisNode, ifTrue: 'merge boundary ⛔️'));
    final Offset? offset = transform != null ? MatrixUtils.getAsTranslation(transform!) : null;
    if (offset != null) {
      properties.add(DiagnosticsProperty<Rect>('rect', rect.shift(offset), showName: false));
    } else {
      final double? scale = transform != null ? MatrixUtils.getAsScale(transform!) : null;
      String? description;
      if (scale != null) {
        description = '$rect scaled by ${scale.toStringAsFixed(1)}x';
      } else if (transform != null && !MatrixUtils.isIdentity(transform!)) {
        final String matrix = transform.toString().split('\n').take(4).map<String>((String line) => line.substring(4)).join('; ');
        description = '$rect with transform [$matrix]';
      }
      properties.add(DiagnosticsProperty<Rect>('rect', rect, description: description, showName: false));
    }
    properties.add(IterableProperty<String>('tags', tags?.map((SemanticsTag tag) => tag.name), defaultValue: null));
    final List<String> actions = _actions.keys.map<String>((SemanticsAction action) => '${action.name}${_debugIsActionBlocked(action) ? '🚫️' : ''}').toList()..sort();
    final List<String?> customSemanticsActions = _customSemanticsActions.keys
      .map<String?>((CustomSemanticsAction action) => action.label)
      .toList();
    properties.add(IterableProperty<String>('actions', actions, ifEmpty: null));
    properties.add(IterableProperty<String?>('customActions', customSemanticsActions, ifEmpty: null));
    final List<String> flags = SemanticsFlag.values.where((SemanticsFlag flag) => hasFlag(flag)).map((SemanticsFlag flag) => flag.name).toList();
    properties.add(IterableProperty<String>('flags', flags, ifEmpty: null));
    properties.add(FlagProperty('isInvisible', value: isInvisible, ifTrue: 'invisible'));
    properties.add(FlagProperty('isHidden', value: hasFlag(SemanticsFlag.isHidden), ifTrue: 'HIDDEN'));
    properties.add(AttributedStringProperty('label', _attributedLabel));
    properties.add(AttributedStringProperty('value', _attributedValue));
    properties.add(AttributedStringProperty('increasedValue', _attributedIncreasedValue));
    properties.add(AttributedStringProperty('decreasedValue', _attributedDecreasedValue));
    properties.add(AttributedStringProperty('hint', _attributedHint));
    properties.add(StringProperty('tooltip', _tooltip, defaultValue: ''));
    properties.add(EnumProperty<TextDirection>('textDirection', _textDirection, defaultValue: null));
    properties.add(DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null));
    if (_textSelection?.isValid ?? false) {
      properties.add(MessageProperty('text selection', '[${_textSelection!.start}, ${_textSelection!.end}]'));
    }
    properties.add(IntProperty('platformViewId', platformViewId, defaultValue: null));
    properties.add(IntProperty('maxValueLength', maxValueLength, defaultValue: null));
    properties.add(IntProperty('currentValueLength', currentValueLength, defaultValue: null));
    properties.add(IntProperty('scrollChildren', scrollChildCount, defaultValue: null));
    properties.add(IntProperty('scrollIndex', scrollIndex, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMin', scrollExtentMin, defaultValue: null));
    properties.add(DoubleProperty('scrollPosition', scrollPosition, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMax', scrollExtentMax, defaultValue: null));
    properties.add(DoubleProperty('elevation', elevation, defaultValue: 0.0));
    properties.add(DoubleProperty('thickness', thickness, defaultValue: 0.0));
  }

  /// Returns a string representation of this node and its descendants.
  ///
  /// The order in which the children of the [SemanticsNode] will be printed is
  /// controlled by the [childOrder] parameter.
  @override
  String toStringDeep({
    String prefixLineOne = '',
    String? prefixOtherLines,
    DiagnosticLevel minLevel = DiagnosticLevel.debug,
    DebugSemanticsDumpOrder childOrder = DebugSemanticsDumpOrder.traversalOrder,
  }) {
    return toDiagnosticsNode(childOrder: childOrder).toStringDeep(prefixLineOne: prefixLineOne, prefixOtherLines: prefixOtherLines, minLevel: minLevel);
  }

  @override
  DiagnosticsNode toDiagnosticsNode({
    String? name,
    DiagnosticsTreeStyle? style = DiagnosticsTreeStyle.sparse,
    DebugSemanticsDumpOrder childOrder = DebugSemanticsDumpOrder.traversalOrder,
  }) {
    return _SemanticsDiagnosticableNode(
      name: name,
      value: this,
      style: style,
      childOrder: childOrder,
    );
  }

  @override
  List<DiagnosticsNode> debugDescribeChildren({ DebugSemanticsDumpOrder childOrder = DebugSemanticsDumpOrder.inverseHitTest }) {
    return debugListChildrenInOrder(childOrder)
      .map<DiagnosticsNode>((SemanticsNode node) => node.toDiagnosticsNode(childOrder: childOrder))
      .toList();
  }

  /// Returns the list of direct children of this node in the specified order.
  List<SemanticsNode> debugListChildrenInOrder(DebugSemanticsDumpOrder childOrder) {
    if (_children == null) {
      return const <SemanticsNode>[];
    }

    switch (childOrder) {
      case DebugSemanticsDumpOrder.inverseHitTest:
        return _children!;
      case DebugSemanticsDumpOrder.traversalOrder:
        return _childrenInTraversalOrder();
    }
  }
}

/// An edge of a box, such as top, bottom, left or right, used to compute
/// [SemanticsNode]s that overlap vertically or horizontally.
///
/// For computing horizontal overlap in an LTR setting we create two [_BoxEdge]
/// objects for each [SemanticsNode]: one representing the left edge (marked
/// with [isLeadingEdge] equal to true) and one for the right edge (with [isLeadingEdge]
/// equal to false). Similarly, for vertical overlap we also create two objects
/// for each [SemanticsNode], one for the top and one for the bottom edge.
class _BoxEdge implements Comparable<_BoxEdge> {
  _BoxEdge({
    required this.isLeadingEdge,
    required this.offset,
    required this.node,
  }) : assert(offset.isFinite);

  /// True if the edge comes before the seconds edge along the traversal
  /// direction, and false otherwise.
  ///
  /// This field is never null.
  ///
  /// For example, in LTR traversal the left edge's [isLeadingEdge] is set to true,
  /// the right edge's [isLeadingEdge] is set to false. When considering vertical
  /// ordering of boxes, the top edge is the start edge, and the bottom edge is
  /// the end edge.
  final bool isLeadingEdge;

  /// The offset from the start edge of the parent [SemanticsNode] in the
  /// direction of the traversal.
  final double offset;

  /// The node whom this edge belongs.
  final SemanticsNode node;

  @override
  int compareTo(_BoxEdge other) {
    return offset.compareTo(other.offset);
  }
}

/// A group of [nodes] that are disjoint vertically or horizontally from other
/// nodes that share the same [SemanticsNode] parent.
///
/// The [nodes] are sorted among each other separately from other nodes.
class _SemanticsSortGroup implements Comparable<_SemanticsSortGroup> {
  _SemanticsSortGroup({
    required this.startOffset,
    required this.textDirection,
  });

  /// The offset from the start edge of the parent [SemanticsNode] in the
  /// direction of the traversal.
  ///
  /// This value is equal to the [_BoxEdge.offset] of the first node in the
  /// [nodes] list being considered.
  final double startOffset;

  final TextDirection textDirection;

  /// The nodes that are sorted among each other.
  final List<SemanticsNode> nodes = <SemanticsNode>[];

  @override
  int compareTo(_SemanticsSortGroup other) {
    return startOffset.compareTo(other.startOffset);
  }

  /// Sorts this group assuming that [nodes] belong to the same vertical group.
  ///
  /// This method breaks up this group into horizontal [_SemanticsSortGroup]s
  /// then sorts them using [sortedWithinKnot].
  List<SemanticsNode> sortedWithinVerticalGroup() {
    final List<_BoxEdge> edges = <_BoxEdge>[];
    for (final SemanticsNode child in nodes) {
      // Using a small delta to shrink child rects removes overlapping cases.
      final Rect childRect = child.rect.deflate(0.1);
      edges.add(_BoxEdge(
        isLeadingEdge: true,
        offset: _pointInParentCoordinates(child, childRect.topLeft).dx,
        node: child,
      ));
      edges.add(_BoxEdge(
        isLeadingEdge: false,
        offset: _pointInParentCoordinates(child, childRect.bottomRight).dx,
        node: child,
      ));
    }
    edges.sort();

    List<_SemanticsSortGroup> horizontalGroups = <_SemanticsSortGroup>[];
    _SemanticsSortGroup? group;
    int depth = 0;
    for (final _BoxEdge edge in edges) {
      if (edge.isLeadingEdge) {
        depth += 1;
        group ??= _SemanticsSortGroup(
          startOffset: edge.offset,
          textDirection: textDirection,
        );
        group.nodes.add(edge.node);
      } else {
        depth -= 1;
      }
      if (depth == 0) {
        horizontalGroups.add(group!);
        group = null;
      }
    }
    horizontalGroups.sort();

    if (textDirection == TextDirection.rtl) {
      horizontalGroups = horizontalGroups.reversed.toList();
    }

    return horizontalGroups
      .expand((_SemanticsSortGroup group) => group.sortedWithinKnot())
      .toList();
  }

  /// Sorts [nodes] where nodes intersect both vertically and horizontally.
  ///
  /// In the special case when [nodes] contains one or less nodes, this method
  /// returns [nodes] unchanged.
  ///
  /// This method constructs a graph, where vertices are [SemanticsNode]s and
  /// edges are "traversed before" relation between pairs of nodes. The sort
  /// order is the topological sorting of the graph, with the original order of
  /// [nodes] used as the tie breaker.
  ///
  /// Whether a node is traversed before another node is determined by the
  /// vector that connects the two nodes' centers. If the vector "points to the
  /// right or down", defined as the [Offset.direction] being between `-pi/4`
  /// and `3*pi/4`), then the semantics node whose center is at the end of the
  /// vector is said to be traversed after.
  List<SemanticsNode> sortedWithinKnot() {
    if (nodes.length <= 1) {
      // Trivial knot. Nothing to do.
      return nodes;
    }
    final Map<int, SemanticsNode> nodeMap = <int, SemanticsNode>{};
    final Map<int, int> edges = <int, int>{};
    for (final SemanticsNode node in nodes) {
      nodeMap[node.id] = node;
      final Offset center = _pointInParentCoordinates(node, node.rect.center);
      for (final SemanticsNode nextNode in nodes) {
        if (identical(node, nextNode) || edges[nextNode.id] == node.id) {
          // Skip self or when we've already established that the next node
          // points to current node.
          continue;
        }

        final Offset nextCenter = _pointInParentCoordinates(nextNode, nextNode.rect.center);
        final Offset centerDelta = nextCenter - center;
        // When centers coincide, direction is 0.0.
        final double direction = centerDelta.direction;
        final bool isLtrAndForward = textDirection == TextDirection.ltr &&
            -math.pi / 4 < direction && direction < 3 * math.pi / 4;
        final bool isRtlAndForward = textDirection == TextDirection.rtl &&
            (direction < -3 * math.pi / 4 || direction > 3 * math.pi / 4);
        if (isLtrAndForward || isRtlAndForward) {
          edges[node.id] = nextNode.id;
        }
      }
    }

    final List<int> sortedIds = <int>[];
    final Set<int> visitedIds = <int>{};
    final List<SemanticsNode> startNodes = nodes.toList()..sort((SemanticsNode a, SemanticsNode b) {
      final Offset aTopLeft = _pointInParentCoordinates(a, a.rect.topLeft);
      final Offset bTopLeft = _pointInParentCoordinates(b, b.rect.topLeft);
      final int verticalDiff = aTopLeft.dy.compareTo(bTopLeft.dy);
      if (verticalDiff != 0) {
        return -verticalDiff;
      }
      return -aTopLeft.dx.compareTo(bTopLeft.dx);
    });

    void search(int id) {
      if (visitedIds.contains(id)) {
        return;
      }
      visitedIds.add(id);
      if (edges.containsKey(id)) {
        search(edges[id]!);
      }
      sortedIds.add(id);
    }

    startNodes.map<int>((SemanticsNode node) => node.id).forEach(search);
    return sortedIds.map<SemanticsNode>((int id) => nodeMap[id]!).toList().reversed.toList();
  }
}

/// Converts `point` to the `node`'s parent's coordinate system.
Offset _pointInParentCoordinates(SemanticsNode node, Offset point) {
  if (node.transform == null) {
    return point;
  }
  final Vector3 vector = Vector3(point.dx, point.dy, 0.0);
  node.transform!.transform3(vector);
  return Offset(vector.x, vector.y);
}

/// Sorts `children` using the default sorting algorithm, and returns them as a
/// new list.
///
/// The algorithm first breaks up children into groups such that no two nodes
/// from different groups overlap vertically. These groups are sorted vertically
/// according to their [_SemanticsSortGroup.startOffset].
///
/// Within each group, the nodes are sorted using
/// [_SemanticsSortGroup.sortedWithinVerticalGroup].
///
/// For an illustration of the algorithm see http://bit.ly/flutter-default-traversal.
List<SemanticsNode> _childrenInDefaultOrder(List<SemanticsNode> children, TextDirection textDirection) {
  final List<_BoxEdge> edges = <_BoxEdge>[];
  for (final SemanticsNode child in children) {
    assert(child.rect.isFinite);
    // Using a small delta to shrink child rects removes overlapping cases.
    final Rect childRect = child.rect.deflate(0.1);
    edges.add(_BoxEdge(
      isLeadingEdge: true,
      offset: _pointInParentCoordinates(child, childRect.topLeft).dy,
      node: child,
    ));
    edges.add(_BoxEdge(
      isLeadingEdge: false,
      offset: _pointInParentCoordinates(child, childRect.bottomRight).dy,
      node: child,
    ));
  }
  edges.sort();

  final List<_SemanticsSortGroup> verticalGroups = <_SemanticsSortGroup>[];
  _SemanticsSortGroup? group;
  int depth = 0;
  for (final _BoxEdge edge in edges) {
    if (edge.isLeadingEdge) {
      depth += 1;
      group ??= _SemanticsSortGroup(
        startOffset: edge.offset,
        textDirection: textDirection,
      );
      group.nodes.add(edge.node);
    } else {
      depth -= 1;
    }
    if (depth == 0) {
      verticalGroups.add(group!);
      group = null;
    }
  }
  verticalGroups.sort();

  return verticalGroups
    .expand((_SemanticsSortGroup group) => group.sortedWithinVerticalGroup())
    .toList();
}

/// The implementation of [Comparable] that implements the ordering of
/// [SemanticsNode]s in the accessibility traversal.
///
/// [SemanticsNode]s are sorted prior to sending them to the engine side.
///
/// This implementation considers a [node]'s [sortKey] and its position within
/// the list of its siblings. [sortKey] takes precedence over position.
class _TraversalSortNode implements Comparable<_TraversalSortNode> {
  _TraversalSortNode({
    required this.node,
    this.sortKey,
    required this.position,
  });

  /// The node whose position this sort node determines.
  final SemanticsNode node;

  /// Determines the position of this node among its siblings.
  ///
  /// Sort keys take precedence over other attributes, such as
  /// [position].
  final SemanticsSortKey? sortKey;

  /// Position within the list of siblings as determined by the default sort
  /// order.
  final int position;

  @override
  int compareTo(_TraversalSortNode other) {
    if (sortKey == null || other.sortKey == null) {
      return position - other.position;
    }
    return sortKey!.compareTo(other.sortKey!);
  }
}

/// Owns [SemanticsNode] objects and notifies listeners of changes to the
/// render tree semantics.
///
/// To listen for semantic updates, call [SemanticsBinding.ensureSemantics] or
/// [PipelineOwner.ensureSemantics] to obtain a [SemanticsHandle]. This will
/// create a [SemanticsOwner] if necessary.
class SemanticsOwner extends ChangeNotifier {
  /// Creates a [SemanticsOwner] that manages zero or more [SemanticsNode] objects.
  SemanticsOwner({
    required this.onSemanticsUpdate,
  });

  /// The [onSemanticsUpdate] callback is expected to dispatch [SemanticsUpdate]s
  /// to the [FlutterView] that is associated with this [PipelineOwner] and/or
  /// [SemanticsOwner].
  ///
  /// A [SemanticsOwner] calls [onSemanticsUpdate] during [sendSemanticsUpdate]
  /// after the [SemanticsUpdate] has been build, but before the [SemanticsOwner]'s
  /// listeners have been notified.
  final SemanticsUpdateCallback onSemanticsUpdate;
  final Set<SemanticsNode> _dirtyNodes = <SemanticsNode>{};
  final Map<int, SemanticsNode> _nodes = <int, SemanticsNode>{};
  final Set<SemanticsNode> _detachedNodes = <SemanticsNode>{};

  /// The root node of the semantics tree, if any.
  ///
  /// If the semantics tree is empty, returns null.
  SemanticsNode? get rootSemanticsNode => _nodes[0];

  @override
  void dispose() {
    _dirtyNodes.clear();
    _nodes.clear();
    _detachedNodes.clear();
    super.dispose();
  }

  /// Update the semantics using [onSemanticsUpdate].
  void sendSemanticsUpdate() {
    if (_dirtyNodes.isEmpty) {
      return;
    }
    final Set<int> customSemanticsActionIds = <int>{};
    final List<SemanticsNode> visitedNodes = <SemanticsNode>[];
    while (_dirtyNodes.isNotEmpty) {
      final List<SemanticsNode> localDirtyNodes = _dirtyNodes.where((SemanticsNode node) => !_detachedNodes.contains(node)).toList();
      _dirtyNodes.clear();
      _detachedNodes.clear();
      localDirtyNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth);
      visitedNodes.addAll(localDirtyNodes);
      for (final SemanticsNode node in localDirtyNodes) {
        assert(node._dirty);
        assert(node.parent == null || !node.parent!.isPartOfNodeMerging || node.isMergedIntoParent);
        if (node.isPartOfNodeMerging) {
          assert(node.mergeAllDescendantsIntoThisNode || node.parent != null);
          // if we're merged into our parent, make sure our parent is added to the dirty list
          if (node.parent != null && node.parent!.isPartOfNodeMerging) {
            node.parent!._markDirty(); // this can add the node to the dirty list
            node._dirty = false; // We don't want to send update for this node.
          }
        }
      }
    }
    visitedNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth);
    final SemanticsUpdateBuilder builder = SemanticsBinding.instance.createSemanticsUpdateBuilder();
    for (final SemanticsNode node in visitedNodes) {
      assert(node.parent?._dirty != true); // could be null (no parent) or false (not dirty)
      // The _serialize() method marks the node as not dirty, and
      // recurses through the tree to do a deep serialization of all
      // contiguous dirty nodes. This means that when we return here,
      // it's quite possible that subsequent nodes are no longer
      // dirty. We skip these here.
      // We also skip any nodes that were reset and subsequently
      // dropped entirely (RenderObject.markNeedsSemanticsUpdate()
      // calls reset() on its SemanticsNode if onlyChanges isn't set,
      // which happens e.g. when the node is no longer contributing
      // semantics).
      if (node._dirty && node.attached) {
        node._addToUpdate(builder, customSemanticsActionIds);
      }
    }
    _dirtyNodes.clear();
    for (final int actionId in customSemanticsActionIds) {
      final CustomSemanticsAction action = CustomSemanticsAction.getAction(actionId)!;
      builder.updateCustomAction(id: actionId, label: action.label, hint: action.hint, overrideId: action.action?.index ?? -1);
    }
    onSemanticsUpdate(builder.build());
    notifyListeners();
  }

  SemanticsActionHandler? _getSemanticsActionHandlerForId(int id, SemanticsAction action) {
    SemanticsNode? result = _nodes[id];
    if (result != null && result.isPartOfNodeMerging && !result._canPerformAction(action)) {
      result._visitDescendants((SemanticsNode node) {
        if (node._canPerformAction(action)) {
          result = node;
          return false; // found node, abort walk
        }
        return true; // continue walk
      });
    }
    if (result == null || !result!._canPerformAction(action)) {
      return null;
    }
    return result!._actions[action];
  }

  /// Asks the [SemanticsNode] with the given id to perform the given action.
  ///
  /// If the [SemanticsNode] has not indicated that it can perform the action,
  /// this function does nothing.
  ///
  /// If the given `action` requires arguments they need to be passed in via
  /// the `args` parameter.
  void performAction(int id, SemanticsAction action, [ Object? args ]) {
    final SemanticsActionHandler? handler = _getSemanticsActionHandlerForId(id, action);
    if (handler != null) {
      handler(args);
      return;
    }

    // Default actions if no [handler] was provided.
    if (action == SemanticsAction.showOnScreen && _nodes[id]?._showOnScreen != null) {
      _nodes[id]!._showOnScreen!();
    }
  }

  SemanticsActionHandler? _getSemanticsActionHandlerForPosition(SemanticsNode node, Offset position, SemanticsAction action) {
    if (node.transform != null) {
      final Matrix4 inverse = Matrix4.identity();
      if (inverse.copyInverse(node.transform!) == 0.0) {
        return null;
      }
      position = MatrixUtils.transformPoint(inverse, position);
    }
    if (!node.rect.contains(position)) {
      return null;
    }
    if (node.mergeAllDescendantsIntoThisNode) {
      SemanticsNode? result;
      node._visitDescendants((SemanticsNode child) {
        if (child._canPerformAction(action)) {
          result = child;
          return false;
        }
        return true;
      });
      return result?._actions[action];
    }
    if (node.hasChildren) {
      for (final SemanticsNode child in node._children!.reversed) {
        final SemanticsActionHandler? handler = _getSemanticsActionHandlerForPosition(child, position, action);
        if (handler != null) {
          return handler;
        }
      }
    }
    return node._actions[action];
  }

  /// Asks the [SemanticsNode] at the given position to perform the given action.
  ///
  /// If the [SemanticsNode] has not indicated that it can perform the action,
  /// this function does nothing.
  ///
  /// If the given `action` requires arguments they need to be passed in via
  /// the `args` parameter.
  void performActionAt(Offset position, SemanticsAction action, [ Object? args ]) {
    final SemanticsNode? node = rootSemanticsNode;
    if (node == null) {
      return;
    }
    final SemanticsActionHandler? handler = _getSemanticsActionHandlerForPosition(node, position, action);
    if (handler != null) {
      handler(args);
    }
  }

  @override
  String toString() => describeIdentity(this);
}

/// Describes the semantic information associated with the owning
/// [RenderObject].
///
/// The information provided in the configuration is used to generate the
/// semantics tree.
class SemanticsConfiguration {

  // SEMANTIC BOUNDARY BEHAVIOR

  /// Whether the [RenderObject] owner of this configuration wants to own its
  /// own [SemanticsNode].
  ///
  /// When set to true semantic information associated with the [RenderObject]
  /// owner of this configuration or any of its descendants will not leak into
  /// parents. The [SemanticsNode] generated out of this configuration will
  /// act as a boundary.
  ///
  /// Whether descendants of the owning [RenderObject] can add their semantic
  /// information to the [SemanticsNode] introduced by this configuration
  /// is controlled by [explicitChildNodes].
  ///
  /// This has to be true if [isMergingSemanticsOfDescendants] is also true.
  bool get isSemanticBoundary => _isSemanticBoundary;
  bool _isSemanticBoundary = false;
  set isSemanticBoundary(bool value) {
    assert(!isMergingSemanticsOfDescendants || value);
    _isSemanticBoundary = value;
  }

  /// Whether to block pointer related user actions for the rendering subtree.
  ///
  /// Setting this to true will prevent users from interacting with the
  /// rendering object produces this semantics configuration and its subtree
  /// through pointer-related [SemanticsAction]s in assistive technologies.
  ///
  /// The [SemanticsNode] created from this semantics configuration is still
  /// focusable by assistive technologies. Only pointer-related
  /// [SemanticsAction]s, such as [SemanticsAction.tap] or its friends, are
  /// blocked.
  ///
  /// If this semantics configuration is merged into a parent semantics node,
  /// only the [SemanticsAction]s from this rendering object and the rendering
  /// objects in the subtree are blocked.
  bool isBlockingUserActions = false;

  /// Whether the configuration forces all children of the owning [RenderObject]
  /// that want to contribute semantic information to the semantics tree to do
  /// so in the form of explicit [SemanticsNode]s.
  ///
  /// When set to false children of the owning [RenderObject] are allowed to
  /// annotate [SemanticsNode]s of their parent with the semantic information
  /// they want to contribute to the semantic tree.
  /// When set to true the only way for children of the owning [RenderObject]
  /// to contribute semantic information to the semantic tree is to introduce
  /// new explicit [SemanticsNode]s to the tree.
  ///
  /// This setting is often used in combination with [isSemanticBoundary] to
  /// create semantic boundaries that are either writable or not for children.
  bool explicitChildNodes = false;

  /// Whether the owning [RenderObject] makes other [RenderObject]s previously
  /// painted within the same semantic boundary unreachable for accessibility
  /// purposes.
  ///
  /// If set to true, the semantic information for all siblings and cousins of
  /// this node, that are earlier in a depth-first pre-order traversal, are
  /// dropped from the semantics tree up until a semantic boundary (as defined
  /// by [isSemanticBoundary]) is reached.
  ///
  /// If [isSemanticBoundary] and [isBlockingSemanticsOfPreviouslyPaintedNodes]
  /// is set on the same node, all previously painted siblings and cousins up
  /// until the next ancestor that is a semantic boundary are dropped.
  ///
  /// Paint order as established by [RenderObject.visitChildrenForSemantics] is
  /// used to determine if a node is previous to this one.
  bool isBlockingSemanticsOfPreviouslyPaintedNodes = false;

  // SEMANTIC ANNOTATIONS
  // These will end up on [SemanticsNode]s generated from
  // [SemanticsConfiguration]s.

  /// Whether this configuration is empty.
  ///
  /// An empty configuration doesn't contain any semantic information that it
  /// wants to contribute to the semantics tree.
  bool get hasBeenAnnotated => _hasBeenAnnotated;
  bool _hasBeenAnnotated = false;

  /// The actions (with associated action handlers) that this configuration
  /// would like to contribute to the semantics tree.
  ///
  /// See also:
  ///
  ///  * [addAction] to add an action.
  final Map<SemanticsAction, SemanticsActionHandler> _actions = <SemanticsAction, SemanticsActionHandler>{};

  int get _effectiveActionsAsBits => isBlockingUserActions ? _actionsAsBits & _kUnblockedUserActions : _actionsAsBits;
  int _actionsAsBits = 0;

  /// Adds an `action` to the semantics tree.
  ///
  /// The provided `handler` is called to respond to the user triggered
  /// `action`.
  void _addAction(SemanticsAction action, SemanticsActionHandler handler) {
    _actions[action] = handler;
    _actionsAsBits |= action.index;
    _hasBeenAnnotated = true;
  }

  /// Adds an `action` to the semantics tree, whose `handler` does not expect
  /// any arguments.
  ///
  /// The provided `handler` is called to respond to the user triggered
  /// `action`.
  void _addArgumentlessAction(SemanticsAction action, VoidCallback handler) {
    _addAction(action, (Object? args) {
      assert(args == null);
      handler();
    });
  }

  /// The handler for [SemanticsAction.tap].
  ///
  /// This is the semantic equivalent of a user briefly tapping the screen with
  /// the finger without moving it. For example, a button should implement this
  /// action.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android can trigger this
  /// action by double-tapping the screen while an element is focused.
  ///
  /// On Android prior to Android Oreo a double-tap on the screen while an
  /// element with an [onTap] handler is focused will not call the registered
  /// handler. Instead, Android will simulate a pointer down and up event at the
  /// center of the focused element. Those pointer events will get dispatched
  /// just like a regular tap with TalkBack disabled would: The events will get
  /// processed by any [GestureDetector] listening for gestures in the center of
  /// the focused element. Therefore, to ensure that [onTap] handlers work
  /// properly on Android versions prior to Oreo, a [GestureDetector] with an
  /// onTap handler should always be wrapping an element that defines a
  /// semantic [onTap] handler. By default a [GestureDetector] will register its
  /// own semantic [onTap] handler that follows this principle.
  VoidCallback? get onTap => _onTap;
  VoidCallback? _onTap;
  set onTap(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.tap, value!);
    _onTap = value;
  }

  /// The handler for [SemanticsAction.longPress].
  ///
  /// This is the semantic equivalent of a user pressing and holding the screen
  /// with the finger for a few seconds without moving it.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android can trigger this
  /// action by double-tapping the screen without lifting the finger after the
  /// second tap.
  VoidCallback? get onLongPress => _onLongPress;
  VoidCallback? _onLongPress;
  set onLongPress(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.longPress, value!);
    _onLongPress = value;
  }

  /// The handler for [SemanticsAction.scrollLeft].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from right to left. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping left with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback? get onScrollLeft => _onScrollLeft;
  VoidCallback? _onScrollLeft;
  set onScrollLeft(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.scrollLeft, value!);
    _onScrollLeft = value;
  }

  /// The handler for [SemanticsAction.dismiss].
  ///
  /// This is a request to dismiss the currently focused node.
  ///
  /// TalkBack users on Android can trigger this action in the local context
  /// menu, and VoiceOver users on iOS can trigger this action with a standard
  /// gesture or menu option.
  VoidCallback? get onDismiss => _onDismiss;
  VoidCallback? _onDismiss;
  set onDismiss(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.dismiss, value!);
    _onDismiss = value;
  }

  /// The handler for [SemanticsAction.scrollRight].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from left to right. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping right with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback? get onScrollRight => _onScrollRight;
  VoidCallback? _onScrollRight;
  set onScrollRight(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.scrollRight, value!);
    _onScrollRight = value;
  }

  /// The handler for [SemanticsAction.scrollUp].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from bottom to top. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback? get onScrollUp => _onScrollUp;
  VoidCallback? _onScrollUp;
  set onScrollUp(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.scrollUp, value!);
    _onScrollUp = value;
  }

  /// The handler for [SemanticsAction.scrollDown].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from top to bottom. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback? get onScrollDown => _onScrollDown;
  VoidCallback? _onScrollDown;
  set onScrollDown(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.scrollDown, value!);
    _onScrollDown = value;
  }

  /// The handler for [SemanticsAction.increase].
  ///
  /// This is a request to increase the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If [this.value] is set, [increasedValue] must also be provided and
  /// [onIncrease] must ensure that [this.value] will be set to
  /// [increasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume up button.
  VoidCallback? get onIncrease => _onIncrease;
  VoidCallback? _onIncrease;
  set onIncrease(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.increase, value!);
    _onIncrease = value;
  }

  /// The handler for [SemanticsAction.decrease].
  ///
  /// This is a request to decrease the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If [this.value] is set, [decreasedValue] must also be provided and
  /// [onDecrease] must ensure that [this.value] will be set to
  /// [decreasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume down button.
  VoidCallback? get onDecrease => _onDecrease;
  VoidCallback? _onDecrease;
  set onDecrease(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.decrease, value!);
    _onDecrease = value;
  }

  /// The handler for [SemanticsAction.copy].
  ///
  /// This is a request to copy the current selection to the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  VoidCallback? get onCopy => _onCopy;
  VoidCallback? _onCopy;
  set onCopy(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.copy, value!);
    _onCopy = value;
  }

  /// The handler for [SemanticsAction.cut].
  ///
  /// This is a request to cut the current selection and place it in the
  /// clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  VoidCallback? get onCut => _onCut;
  VoidCallback? _onCut;
  set onCut(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.cut, value!);
    _onCut = value;
  }

  /// The handler for [SemanticsAction.paste].
  ///
  /// This is a request to paste the current content of the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  VoidCallback? get onPaste => _onPaste;
  VoidCallback? _onPaste;
  set onPaste(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.paste, value!);
    _onPaste = value;
  }

  /// The handler for [SemanticsAction.showOnScreen].
  ///
  /// A request to fully show the semantics node on screen. For example, this
  /// action might be send to a node in a scrollable list that is partially off
  /// screen to bring it on screen.
  ///
  /// For elements in a scrollable list the framework provides a default
  /// implementation for this action and it is not advised to provide a
  /// custom one via this setter.
  VoidCallback? get onShowOnScreen => _onShowOnScreen;
  VoidCallback? _onShowOnScreen;
  set onShowOnScreen(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.showOnScreen, value!);
    _onShowOnScreen = value;
  }

  /// The handler for [SemanticsAction.moveCursorForwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field forward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume up key while the
  /// input focus is in a text field.
  MoveCursorHandler? get onMoveCursorForwardByCharacter => _onMoveCursorForwardByCharacter;
  MoveCursorHandler? _onMoveCursorForwardByCharacter;
  set onMoveCursorForwardByCharacter(MoveCursorHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorForwardByCharacter, (Object? args) {
      final bool extendSelection = args! as bool;
      value!(extendSelection);
    });
    _onMoveCursorForwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.moveCursorBackwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  MoveCursorHandler? get onMoveCursorBackwardByCharacter => _onMoveCursorBackwardByCharacter;
  MoveCursorHandler? _onMoveCursorBackwardByCharacter;
  set onMoveCursorBackwardByCharacter(MoveCursorHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorBackwardByCharacter, (Object? args) {
      final bool extendSelection = args! as bool;
      value!(extendSelection);
    });
    _onMoveCursorBackwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.moveCursorForwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  MoveCursorHandler? get onMoveCursorForwardByWord => _onMoveCursorForwardByWord;
  MoveCursorHandler? _onMoveCursorForwardByWord;
  set onMoveCursorForwardByWord(MoveCursorHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorForwardByWord, (Object? args) {
      final bool extendSelection = args! as bool;
      value!(extendSelection);
    });
    _onMoveCursorForwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.moveCursorBackwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  MoveCursorHandler? get onMoveCursorBackwardByWord => _onMoveCursorBackwardByWord;
  MoveCursorHandler? _onMoveCursorBackwardByWord;
  set onMoveCursorBackwardByWord(MoveCursorHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorBackwardByWord, (Object? args) {
      final bool extendSelection = args! as bool;
      value!(extendSelection);
    });
    _onMoveCursorBackwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.setSelection].
  ///
  /// This handler is invoked when the user either wants to change the currently
  /// selected text in a text field or change the position of the cursor.
  ///
  /// TalkBack users can trigger this handler by selecting "Move cursor to
  /// beginning/end" or "Select all" from the local context menu.
  SetSelectionHandler? get onSetSelection => _onSetSelection;
  SetSelectionHandler? _onSetSelection;
  set onSetSelection(SetSelectionHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.setSelection, (Object? args) {
      assert(args != null && args is Map);
      final Map<String, int> selection = (args! as Map<dynamic, dynamic>).cast<String, int>();
      assert(selection['base'] != null && selection['extent'] != null);
      value!(TextSelection(
        baseOffset: selection['base']!,
        extentOffset: selection['extent']!,
      ));
    });
    _onSetSelection = value;
  }

  /// The handler for [SemanticsAction.setText].
  ///
  /// This handler is invoked when the user wants to replace the current text in
  /// the text field with a new text.
  ///
  /// Voice access users can trigger this handler by speaking "type <text>" to
  /// their Android devices.
  SetTextHandler? get onSetText => _onSetText;
  SetTextHandler? _onSetText;
  set onSetText(SetTextHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.setText, (Object? args) {
      assert(args != null && args is String);
      final String text = args! as String;
      value!(text);
    });
    _onSetText = value;
  }

  /// The handler for [SemanticsAction.didGainAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler gains
  /// the accessibility focus. The accessibility focus is the
  /// green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidLoseAccessibilityFocus], which is invoked when the accessibility
  ///    focus is removed from the node.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  VoidCallback? get onDidGainAccessibilityFocus => _onDidGainAccessibilityFocus;
  VoidCallback? _onDidGainAccessibilityFocus;
  set onDidGainAccessibilityFocus(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.didGainAccessibilityFocus, value!);
    _onDidGainAccessibilityFocus = value;
  }

  /// The handler for [SemanticsAction.didLoseAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler
  /// loses the accessibility focus. The accessibility focus is
  /// the green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidGainAccessibilityFocus], which is invoked when the node gains
  ///    accessibility focus.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  VoidCallback? get onDidLoseAccessibilityFocus => _onDidLoseAccessibilityFocus;
  VoidCallback? _onDidLoseAccessibilityFocus;
  set onDidLoseAccessibilityFocus(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.didLoseAccessibilityFocus, value!);
    _onDidLoseAccessibilityFocus = value;
  }

  /// A delegate that decides how to handle [SemanticsConfiguration]s produced
  /// in the widget subtree.
  ///
  /// The [SemanticsConfiguration]s are produced by rendering objects in the
  /// subtree and want to merge up to their parent. This delegate can decide
  /// which of these should be merged together to form sibling SemanticsNodes and
  /// which of them should be merged upwards into the parent SemanticsNode.
  ///
  /// The input list of [SemanticsConfiguration]s can be empty if the rendering
  /// object of this semantics configuration is a leaf node or child rendering
  /// objects do not contribute to the semantics.
  ChildSemanticsConfigurationsDelegate? get childConfigurationsDelegate => _childConfigurationsDelegate;
  ChildSemanticsConfigurationsDelegate? _childConfigurationsDelegate;
  set childConfigurationsDelegate(ChildSemanticsConfigurationsDelegate? value) {
    assert(value != null);
    _childConfigurationsDelegate = value;
    // Setting the childConfigsDelegate does not annotate any meaningful
    // semantics information of the config.
  }

  /// Returns the action handler registered for [action] or null if none was
  /// registered.
  SemanticsActionHandler? getActionHandler(SemanticsAction action) => _actions[action];

  /// Determines the position of this node among its siblings in the traversal
  /// sort order.
  ///
  /// This is used to describe the order in which the semantic node should be
  /// traversed by the accessibility services on the platform (e.g. VoiceOver
  /// on iOS and TalkBack on Android).
  ///
  /// Whether this sort key has an effect on the [SemanticsNode] sort order is
  /// subject to how this configuration is used. For example, the [absorb]
  /// method may decide to not use this key when it combines multiple
  /// [SemanticsConfiguration] objects.
  SemanticsSortKey? get sortKey => _sortKey;
  SemanticsSortKey? _sortKey;
  set sortKey(SemanticsSortKey? value) {
    assert(value != null);
    _sortKey = value;
    _hasBeenAnnotated = true;
  }

  /// The index of this node within the parent's list of semantic children.
  ///
  /// This includes all semantic nodes, not just those currently in the
  /// child list. For example, if a scrollable has five children but the first
  /// two are not visible (and thus not included in the list of children), then
  /// the index of the last node will still be 4.
  int? get indexInParent => _indexInParent;
  int? _indexInParent;
  set indexInParent(int? value) {
    _indexInParent = value;
    _hasBeenAnnotated = true;
  }

  /// The total number of scrollable children that contribute to semantics.
  ///
  /// If the number of children are unknown or unbounded, this value will be
  /// null.
  int? get scrollChildCount => _scrollChildCount;
  int? _scrollChildCount;
  set scrollChildCount(int? value) {
    if (value == scrollChildCount) {
      return;
    }
    _scrollChildCount = value;
    _hasBeenAnnotated = true;
  }

  /// The index of the first visible scrollable child that contributes to
  /// semantics.
  int? get scrollIndex => _scrollIndex;
  int? _scrollIndex;
  set scrollIndex(int? value) {
    if (value == scrollIndex) {
      return;
    }
    _scrollIndex = value;
    _hasBeenAnnotated = true;
  }

  /// The id of the platform view, whose semantics nodes will be added as
  /// children to this node.
  int? get platformViewId => _platformViewId;
  int? _platformViewId;
  set platformViewId(int? value) {
    if (value == platformViewId) {
      return;
    }
    _platformViewId = value;
    _hasBeenAnnotated = true;
  }

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [isTextField] is true. Defaults to null,
  /// which means no limit is imposed on the text field.
  int? get maxValueLength => _maxValueLength;
  int? _maxValueLength;
  set maxValueLength(int? value) {
    if (value == maxValueLength) {
      return;
    }
    _maxValueLength = value;
    _hasBeenAnnotated = true;
  }

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [isTextField] is true. Must be set when
  /// [maxValueLength] is set.
  int? get currentValueLength => _currentValueLength;
  int? _currentValueLength;
  set currentValueLength(int? value) {
    if (value == currentValueLength) {
      return;
    }
    _currentValueLength = value;
    _hasBeenAnnotated = true;
  }

  /// Whether the semantic information provided by the owning [RenderObject] and
  /// all of its descendants should be treated as one logical entity.
  ///
  /// If set to true, the descendants of the owning [RenderObject]'s
  /// [SemanticsNode] will merge their semantic information into the
  /// [SemanticsNode] representing the owning [RenderObject].
  ///
  /// Setting this to true requires that [isSemanticBoundary] is also true.
  bool get isMergingSemanticsOfDescendants => _isMergingSemanticsOfDescendants;
  bool _isMergingSemanticsOfDescendants = false;
  set isMergingSemanticsOfDescendants(bool value) {
    assert(isSemanticBoundary);
    _isMergingSemanticsOfDescendants = value;
    _hasBeenAnnotated = true;
  }

  /// The handlers for each supported [CustomSemanticsAction].
  ///
  /// Whenever a custom accessibility action is added to a node, the action
  /// [SemanticsAction.customAction] is automatically added. A handler is
  /// created which uses the passed argument to lookup the custom action
  /// handler from this map and invoke it, if present.
  Map<CustomSemanticsAction, VoidCallback> get customSemanticsActions => _customSemanticsActions;
  Map<CustomSemanticsAction, VoidCallback> _customSemanticsActions = <CustomSemanticsAction, VoidCallback>{};
  set customSemanticsActions(Map<CustomSemanticsAction, VoidCallback> value) {
    _hasBeenAnnotated = true;
    _actionsAsBits |= SemanticsAction.customAction.index;
    _customSemanticsActions = value;
    _actions[SemanticsAction.customAction] = _onCustomSemanticsAction;
  }

  void _onCustomSemanticsAction(Object? args) {
    final CustomSemanticsAction? action = CustomSemanticsAction.getAction(args! as int);
    if (action == null) {
      return;
    }
    final VoidCallback? callback = _customSemanticsActions[action];
    if (callback != null) {
      callback();
    }
  }

  /// A textual description of the owning [RenderObject].
  ///
  /// Setting this attribute will override the [attributedLabel].
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [attributedLabel], which is the [AttributedString] of this property.
  String get label => _attributedLabel.string;
  set label(String label) {
    _attributedLabel = AttributedString(label);
    _hasBeenAnnotated = true;
  }

  /// A textual description of the owning [RenderObject] in [AttributedString]
  /// format.
  ///
  /// On iOS this is used for the `accessibilityAttributedLabel` property
  /// defined in the `UIAccessibility` Protocol. On Android it is concatenated
  /// together with [attributedValue] and [attributedHint] in the following
  /// order: [attributedValue], [attributedLabel], [attributedHint]. The
  /// concatenated value is then used as the `Text` description.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [label], which is the raw text of this property.
  AttributedString get attributedLabel => _attributedLabel;
  AttributedString _attributedLabel = AttributedString('');
  set attributedLabel(AttributedString attributedLabel) {
    _attributedLabel = attributedLabel;
    _hasBeenAnnotated = true;
  }

  /// A textual description for the current value of the owning [RenderObject].
  ///
  /// Setting this attribute will override the [attributedValue].
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [attributedValue], which is the [AttributedString] of this property.
  ///  * [increasedValue] and [attributedIncreasedValue], which describe what
  ///    [value] will be after performing [SemanticsAction.increase].
  ///  * [decreasedValue] and [attributedDecreasedValue], which describe what
  ///    [value] will be after performing [SemanticsAction.decrease].
  String get value => _attributedValue.string;
  set value(String value) {
    _attributedValue = AttributedString(value);
    _hasBeenAnnotated = true;
  }

  /// A textual description for the current value of the owning [RenderObject]
  /// in [AttributedString] format.
  ///
  /// On iOS this is used for the `accessibilityAttributedValue` property
  /// defined in the `UIAccessibility` Protocol. On Android it is concatenated
  /// together with [attributedLabel] and [attributedHint] in the following
  /// order: [attributedValue], [attributedLabel], [attributedHint]. The
  /// concatenated value is then used as the `Text` description.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [value], which is the raw text of this property.
  ///  * [attributedIncreasedValue], which describes what [value] will be after
  ///    performing [SemanticsAction.increase].
  ///  * [attributedDecreasedValue], which describes what [value] will be after
  ///    performing [SemanticsAction.decrease].
  AttributedString get attributedValue => _attributedValue;
  AttributedString _attributedValue = AttributedString('');
  set attributedValue(AttributedString attributedValue) {
    _attributedValue = attributedValue;
    _hasBeenAnnotated = true;
  }

  /// The value that [value] will have after performing a
  /// [SemanticsAction.increase] action.
  ///
  /// Setting this attribute will override the [attributedIncreasedValue].
  ///
  /// One of the [attributedIncreasedValue] or [increasedValue] must be set if
  /// a handler for [SemanticsAction.increase] is provided and one of the
  /// [value] or [attributedValue] is set.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [attributedIncreasedValue], which is the [AttributedString] of this property.
  String get increasedValue => _attributedIncreasedValue.string;
  set increasedValue(String increasedValue) {
    _attributedIncreasedValue = AttributedString(increasedValue);
    _hasBeenAnnotated = true;
  }

  /// The value that [value] will have after performing a
  /// [SemanticsAction.increase] action in [AttributedString] format.
  ///
  /// One of the [attributedIncreasedValue] or [increasedValue] must be set if
  /// a handler for [SemanticsAction.increase] is provided and one of the
  /// [value] or [attributedValue] is set.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [increasedValue], which is the raw text of this property.
  AttributedString get attributedIncreasedValue => _attributedIncreasedValue;
  AttributedString _attributedIncreasedValue = AttributedString('');
  set attributedIncreasedValue(AttributedString attributedIncreasedValue) {
    _attributedIncreasedValue = attributedIncreasedValue;
    _hasBeenAnnotated = true;
  }

  /// The value that [value] will have after performing a
  /// [SemanticsAction.decrease] action.
  ///
  /// Setting this attribute will override the [attributedDecreasedValue].
  ///
  /// One of the [attributedDecreasedValue] or [decreasedValue] must be set if
  /// a handler for [SemanticsAction.decrease] is provided and one of the
  /// [value] or [attributedValue] is set.
  ///
  /// The reading direction is given by [textDirection].
  ///
  ///  * [attributedDecreasedValue], which is the [AttributedString] of this property.
  String get decreasedValue => _attributedDecreasedValue.string;
  set decreasedValue(String decreasedValue) {
    _attributedDecreasedValue = AttributedString(decreasedValue);
    _hasBeenAnnotated = true;
  }

  /// The value that [value] will have after performing a
  /// [SemanticsAction.decrease] action in [AttributedString] format.
  ///
  /// One of the [attributedDecreasedValue] or [decreasedValue] must be set if
  /// a handler for [SemanticsAction.decrease] is provided and one of the
  /// [value] or [attributedValue] is set.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [decreasedValue], which is the raw text of this property.
  AttributedString get attributedDecreasedValue => _attributedDecreasedValue;
  AttributedString _attributedDecreasedValue = AttributedString('');
  set attributedDecreasedValue(AttributedString attributedDecreasedValue) {
    _attributedDecreasedValue = attributedDecreasedValue;
    _hasBeenAnnotated = true;
  }

  /// A brief description of the result of performing an action on this node.
  ///
  /// Setting this attribute will override the [attributedHint].
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [attributedHint], which is the [AttributedString] of this property.
  String get hint => _attributedHint.string;
  set hint(String hint) {
    _attributedHint = AttributedString(hint);
    _hasBeenAnnotated = true;
  }

  /// A brief description of the result of performing an action on this node in
  /// [AttributedString] format.
  ///
  /// On iOS this is used for the `accessibilityAttributedHint` property
  /// defined in the `UIAccessibility` Protocol. On Android it is concatenated
  /// together with [attributedLabel] and [attributedValue] in the following
  /// order: [attributedValue], [attributedLabel], [attributedHint]. The
  /// concatenated value is then used as the `Text` description.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [hint], which is the raw text of this property.
  AttributedString get attributedHint => _attributedHint;
  AttributedString _attributedHint = AttributedString('');
  set attributedHint(AttributedString attributedHint) {
    _attributedHint = attributedHint;
    _hasBeenAnnotated = true;
  }

  /// A textual description of the widget's tooltip.
  ///
  /// The reading direction is given by [textDirection].
  String get tooltip => _tooltip;
  String _tooltip = '';
  set tooltip(String tooltip) {
    _tooltip = tooltip;
    _hasBeenAnnotated = true;
  }

  /// Provides hint values which override the default hints on supported
  /// platforms.
  SemanticsHintOverrides? get hintOverrides => _hintOverrides;
  SemanticsHintOverrides? _hintOverrides;
  set hintOverrides(SemanticsHintOverrides? value) {
    if (value == null) {
      return;
    }
    _hintOverrides = value;
    _hasBeenAnnotated = true;
  }

  /// The elevation in z-direction at which the owning [RenderObject] is
  /// located relative to its parent.
  double get elevation => _elevation;
  double _elevation = 0.0;
  set elevation(double value) {
    assert(value >= 0.0);
    if (value == _elevation) {
      return;
    }
    _elevation = value;
    _hasBeenAnnotated = true;
  }

  /// The extend that the owning [RenderObject] occupies in z-direction starting
  /// at [elevation].
  ///
  /// It's extremely rare to set this value directly. Instead, it is calculated
  /// implicitly when other [SemanticsConfiguration]s are merged into this one
  /// via [absorb].
  double get thickness => _thickness;
  double _thickness = 0.0;
  set thickness(double value) {
    assert(value >= 0.0);
    if (value == _thickness) {
      return;
    }
    _thickness = value;
    _hasBeenAnnotated = true;
  }

  /// Whether the semantics node is the root of a subtree for which values
  /// should be announced.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.scopesRoute], for a full description of route scoping.
  bool get scopesRoute => _hasFlag(SemanticsFlag.scopesRoute);
  set scopesRoute(bool value) {
    _setFlag(SemanticsFlag.scopesRoute, value);
  }

  /// Whether the semantics node contains the label of a route.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.namesRoute], for a full description of route naming.
  bool get namesRoute => _hasFlag(SemanticsFlag.namesRoute);
  set namesRoute(bool value) {
    _setFlag(SemanticsFlag.namesRoute, value);
  }

  /// Whether the semantics node represents an image.
  bool get isImage => _hasFlag(SemanticsFlag.isImage);
  set isImage(bool value) {
    _setFlag(SemanticsFlag.isImage, value);
  }

  /// Whether the semantics node is a live region.
  ///
  /// A live region indicates that updates to semantics node are important.
  /// Platforms may use this information to make polite announcements to the
  /// user to inform them of updates to this node.
  ///
  /// An example of a live region is a [SnackBar] widget. On Android and iOS,
  /// live region causes a polite announcement to be generated automatically,
  /// even if the widget does not have accessibility focus. This announcement
  /// may not be spoken if the OS accessibility services are already
  /// announcing something else, such as reading the label of a focused widget
  /// or providing a system announcement.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.isLiveRegion], the semantics flag that this setting controls.
  bool get liveRegion => _hasFlag(SemanticsFlag.isLiveRegion);
  set liveRegion(bool value) {
    _setFlag(SemanticsFlag.isLiveRegion, value);
  }

  /// The reading direction for the text in [label], [value], [hint],
  /// [increasedValue], and [decreasedValue].
  TextDirection? get textDirection => _textDirection;
  TextDirection? _textDirection;
  set textDirection(TextDirection? textDirection) {
    _textDirection = textDirection;
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is selected (true) or not (false).
  ///
  /// This is different from having accessibility focus. The element that is
  /// accessibility focused may or may not be selected; e.g. a [ListTile] can have
  /// accessibility focus but have its [ListTile.selected] property set to false,
  /// in which case it will not be flagged as selected.
  bool get isSelected => _hasFlag(SemanticsFlag.isSelected);
  set isSelected(bool value) {
    _setFlag(SemanticsFlag.isSelected, value);
  }

  /// Whether the owning [RenderObject] is currently enabled.
  ///
  /// A disabled object does not respond to user interactions. Only objects that
  /// usually respond to user interactions, but which currently do not (like a
  /// disabled button) should be marked as disabled.
  ///
  /// The setter should not be called for objects (like static text) that never
  /// respond to user interactions.
  ///
  /// The getter will return null if the owning [RenderObject] doesn't support
  /// the concept of being enabled/disabled.
  ///
  /// This property does not control whether semantics are enabled. If you wish to
  /// disable semantics for a particular widget, you should use an [ExcludeSemantics]
  /// widget.
  bool? get isEnabled => _hasFlag(SemanticsFlag.hasEnabledState) ? _hasFlag(SemanticsFlag.isEnabled) : null;
  set isEnabled(bool? value) {
    _setFlag(SemanticsFlag.hasEnabledState, true);
    _setFlag(SemanticsFlag.isEnabled, value!);
  }

  /// If this node has Boolean state that can be controlled by the user, whether
  /// that state is checked or unchecked, corresponding to true and false,
  /// respectively.
  ///
  /// Do not call the setter for this field if the owning [RenderObject] doesn't
  /// have checked/unchecked state that can be controlled by the user.
  ///
  /// The getter returns null if the owning [RenderObject] does not have
  /// checked/unchecked state.
  bool? get isChecked => _hasFlag(SemanticsFlag.hasCheckedState) ? _hasFlag(SemanticsFlag.isChecked) : null;
  set isChecked(bool? value) {
    assert(value != true || isCheckStateMixed != true);
    _setFlag(SemanticsFlag.hasCheckedState, true);
    _setFlag(SemanticsFlag.isChecked, value!);
  }

  /// If this node has tristate that can be controlled by the user, whether
  /// that state is in its mixed state.
  ///
  /// Do not call the setter for this field if the owning [RenderObject] doesn't
  /// have checked/unchecked state that can be controlled by the user.
  ///
  /// The getter returns null if the owning [RenderObject] does not have
  /// mixed checked state.
  bool? get isCheckStateMixed => _hasFlag(SemanticsFlag.hasCheckedState) ? _hasFlag(SemanticsFlag.isCheckStateMixed) : null;
  set isCheckStateMixed(bool? value) {
    assert(value != true || isChecked != true);
    _setFlag(SemanticsFlag.hasCheckedState, true);
    _setFlag(SemanticsFlag.isCheckStateMixed, value!);
  }

  /// If this node has Boolean state that can be controlled by the user, whether
  /// that state is on or off, corresponding to true and false, respectively.
  ///
  /// Do not call the setter for this field if the owning [RenderObject] doesn't
  /// have on/off state that can be controlled by the user.
  ///
  /// The getter returns null if the owning [RenderObject] does not have
  /// on/off state.
  bool? get isToggled => _hasFlag(SemanticsFlag.hasToggledState) ? _hasFlag(SemanticsFlag.isToggled) : null;
  set isToggled(bool? value) {
    _setFlag(SemanticsFlag.hasToggledState, true);
    _setFlag(SemanticsFlag.isToggled, value!);
  }

  /// Whether the owning RenderObject corresponds to UI that allows the user to
  /// pick one of several mutually exclusive options.
  ///
  /// For example, a [Radio] button is in a mutually exclusive group because
  /// only one radio button in that group can be marked as [isChecked].
  bool get isInMutuallyExclusiveGroup => _hasFlag(SemanticsFlag.isInMutuallyExclusiveGroup);
  set isInMutuallyExclusiveGroup(bool value) {
    _setFlag(SemanticsFlag.isInMutuallyExclusiveGroup, value);
  }

  /// Whether the owning [RenderObject] can hold the input focus.
  bool get isFocusable => _hasFlag(SemanticsFlag.isFocusable);
  set isFocusable(bool value) {
    _setFlag(SemanticsFlag.isFocusable, value);
  }

  /// Whether the owning [RenderObject] currently holds the input focus.
  bool get isFocused => _hasFlag(SemanticsFlag.isFocused);
  set isFocused(bool value) {
    _setFlag(SemanticsFlag.isFocused, value);
  }

  /// Whether the owning [RenderObject] is a button (true) or not (false).
  bool get isButton => _hasFlag(SemanticsFlag.isButton);
  set isButton(bool value) {
    _setFlag(SemanticsFlag.isButton, value);
  }

  /// Whether the owning [RenderObject] is a link (true) or not (false).
  bool get isLink => _hasFlag(SemanticsFlag.isLink);
  set isLink(bool value) {
    _setFlag(SemanticsFlag.isLink, value);
  }

  /// Whether the owning [RenderObject] is a header (true) or not (false).
  bool get isHeader => _hasFlag(SemanticsFlag.isHeader);
  set isHeader(bool value) {
    _setFlag(SemanticsFlag.isHeader, value);
  }

  /// Whether the owning [RenderObject] is a slider (true) or not (false).
  bool get isSlider => _hasFlag(SemanticsFlag.isSlider);
  set isSlider(bool value) {
    _setFlag(SemanticsFlag.isSlider, value);
  }

  /// Whether the owning [RenderObject] is a keyboard key (true) or not
  //(false).
  bool get isKeyboardKey => _hasFlag(SemanticsFlag.isKeyboardKey);
  set isKeyboardKey(bool value) {
    _setFlag(SemanticsFlag.isKeyboardKey, value);
  }

  /// Whether the owning [RenderObject] is considered hidden.
  ///
  /// Hidden elements are currently not visible on screen. They may be covered
  /// by other elements or positioned outside of the visible area of a viewport.
  ///
  /// Hidden elements cannot gain accessibility focus though regular touch. The
  /// only way they can be focused is by moving the focus to them via linear
  /// navigation.
  ///
  /// Platforms are free to completely ignore hidden elements and new platforms
  /// are encouraged to do so.
  ///
  /// Instead of marking an element as hidden it should usually be excluded from
  /// the semantics tree altogether. Hidden elements are only included in the
  /// semantics tree to work around platform limitations and they are mainly
  /// used to implement accessibility scrolling on iOS.
  bool get isHidden => _hasFlag(SemanticsFlag.isHidden);
  set isHidden(bool value) {
    _setFlag(SemanticsFlag.isHidden, value);
  }

  /// Whether the owning [RenderObject] is a text field.
  bool get isTextField => _hasFlag(SemanticsFlag.isTextField);
  set isTextField(bool value) {
    _setFlag(SemanticsFlag.isTextField, value);
  }

  /// Whether the owning [RenderObject] is read only.
  ///
  /// Only applicable when [isTextField] is true.
  bool get isReadOnly => _hasFlag(SemanticsFlag.isReadOnly);
  set isReadOnly(bool value) {
    _setFlag(SemanticsFlag.isReadOnly, value);
  }

  /// Whether [this.value] should be obscured.
  ///
  /// This option is usually set in combination with [isTextField] to indicate
  /// that the text field contains a password (or other sensitive information).
  /// Doing so instructs screen readers to not read out [this.value].
  bool get isObscured => _hasFlag(SemanticsFlag.isObscured);
  set isObscured(bool value) {
    _setFlag(SemanticsFlag.isObscured, value);
  }

  /// Whether the text field is multiline.
  ///
  /// This option is usually set in combination with [isTextField] to indicate
  /// that the text field is configured to be multiline.
  bool get isMultiline => _hasFlag(SemanticsFlag.isMultiline);
  set isMultiline(bool value) {
    _setFlag(SemanticsFlag.isMultiline, value);
  }

  /// Whether the platform can scroll the semantics node when the user attempts
  /// to move focus to an offscreen child.
  ///
  /// For example, a [ListView] widget has implicit scrolling so that users can
  /// easily move to the next visible set of children. A [TabBar] widget does
  /// not have implicit scrolling, so that users can navigate into the tab
  /// body when reaching the end of the tab bar.
  bool get hasImplicitScrolling => _hasFlag(SemanticsFlag.hasImplicitScrolling);
  set hasImplicitScrolling(bool value) {
    _setFlag(SemanticsFlag.hasImplicitScrolling, value);
  }

  /// The currently selected text (or the position of the cursor) within
  /// [this.value] if this node represents a text field.
  TextSelection? get textSelection => _textSelection;
  TextSelection? _textSelection;
  set textSelection(TextSelection? value) {
    assert(value != null);
    _textSelection = value;
    _hasBeenAnnotated = true;
  }

  /// Indicates the current scrolling position in logical pixels if the node is
  /// scrollable.
  ///
  /// The properties [scrollExtentMin] and [scrollExtentMax] indicate the valid
  /// in-range values for this property. The value for [scrollPosition] may
  /// (temporarily) be outside that range, e.g. during an overscroll.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.pixels], from where this value is usually taken.
  double? get scrollPosition => _scrollPosition;
  double? _scrollPosition;
  set scrollPosition(double? value) {
    assert(value != null);
    _scrollPosition = value;
    _hasBeenAnnotated = true;
  }

  /// Indicates the maximum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.maxScrollExtent], from where this value is usually taken.
  double? get scrollExtentMax => _scrollExtentMax;
  double? _scrollExtentMax;
  set scrollExtentMax(double? value) {
    assert(value != null);
    _scrollExtentMax = value;
    _hasBeenAnnotated = true;
  }

  /// Indicates the minimum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.minScrollExtent], from where this value is usually taken.
  double? get scrollExtentMin => _scrollExtentMin;
  double? _scrollExtentMin;
  set scrollExtentMin(double? value) {
    assert(value != null);
    _scrollExtentMin = value;
    _hasBeenAnnotated = true;
  }

  // TAGS

  /// The set of tags that this configuration wants to add to all child
  /// [SemanticsNode]s.
  ///
  /// See also:
  ///
  ///  * [addTagForChildren] to add a tag and for more information about their
  ///    usage.
  Iterable<SemanticsTag>? get tagsForChildren => _tagsForChildren;

  /// Whether this configuration will tag the child semantics nodes with a
  /// given [SemanticsTag].
  bool tagsChildrenWith(SemanticsTag tag) => _tagsForChildren?.contains(tag) ?? false;

  Set<SemanticsTag>? _tagsForChildren;

  /// Specifies a [SemanticsTag] that this configuration wants to apply to all
  /// child [SemanticsNode]s.
  ///
  /// The tag is added to all [SemanticsNode] that pass through the
  /// [RenderObject] owning this configuration while looking to be attached to a
  /// parent [SemanticsNode].
  ///
  /// Tags are used to communicate to a parent [SemanticsNode] that a child
  /// [SemanticsNode] was passed through a particular [RenderObject]. The parent
  /// can use this information to determine the shape of the semantics tree.
  ///
  /// See also:
  ///
  ///  * [RenderViewport.excludeFromScrolling] for an example of
  ///    how tags are used.
  void addTagForChildren(SemanticsTag tag) {
    _tagsForChildren ??= <SemanticsTag>{};
    _tagsForChildren!.add(tag);
  }

  // INTERNAL FLAG MANAGEMENT

  int _flags = 0;
  void _setFlag(SemanticsFlag flag, bool value) {
    if (value) {
      _flags |= flag.index;
    } else {
      _flags &= ~flag.index;
    }
    _hasBeenAnnotated = true;
  }

  bool _hasFlag(SemanticsFlag flag) => (_flags & flag.index) != 0;

  // CONFIGURATION COMBINATION LOGIC

  /// Whether this configuration is compatible with the provided `other`
  /// configuration.
  ///
  /// Two configurations are said to be compatible if they can be added to the
  /// same [SemanticsNode] without losing any semantics information.
  bool isCompatibleWith(SemanticsConfiguration? other) {
    if (other == null || !other.hasBeenAnnotated || !hasBeenAnnotated) {
      return true;
    }
    if (_actionsAsBits & other._actionsAsBits != 0) {
      return false;
    }
    if ((_flags & other._flags) != 0) {
      return false;
    }
    if (_platformViewId != null && other._platformViewId != null) {
      return false;
    }
    if (_maxValueLength != null && other._maxValueLength != null) {
      return false;
    }
    if (_currentValueLength != null && other._currentValueLength != null) {
      return false;
    }
    if (_attributedValue.string.isNotEmpty && other._attributedValue.string.isNotEmpty) {
      return false;
    }
    return true;
  }

  /// Absorb the semantic information from `child` into this configuration.
  ///
  /// This adds the semantic information of both configurations and saves the
  /// result in this configuration.
  ///
  /// The [RenderObject] owning the `child` configuration must be a descendant
  /// of the [RenderObject] that owns this configuration.
  ///
  /// Only configurations that have [explicitChildNodes] set to false can
  /// absorb other configurations and it is recommended to only absorb compatible
  /// configurations as determined by [isCompatibleWith].
  void absorb(SemanticsConfiguration child) {
    assert(!explicitChildNodes);

    if (!child.hasBeenAnnotated) {
      return;
    }
    if (child.isBlockingUserActions) {
      child._actions.forEach((SemanticsAction key, SemanticsActionHandler value) {
        if (_kUnblockedUserActions & key.index > 0) {
          _actions[key] = value;
        }
      });
    } else {
      _actions.addAll(child._actions);
    }
    _actionsAsBits |= child._effectiveActionsAsBits;
    _customSemanticsActions.addAll(child._customSemanticsActions);
    _flags |= child._flags;
    _textSelection ??= child._textSelection;
    _scrollPosition ??= child._scrollPosition;
    _scrollExtentMax ??= child._scrollExtentMax;
    _scrollExtentMin ??= child._scrollExtentMin;
    _hintOverrides ??= child._hintOverrides;
    _indexInParent ??= child.indexInParent;
    _scrollIndex ??= child._scrollIndex;
    _scrollChildCount ??= child._scrollChildCount;
    _platformViewId ??= child._platformViewId;
    _maxValueLength ??= child._maxValueLength;
    _currentValueLength ??= child._currentValueLength;

    textDirection ??= child.textDirection;
    _sortKey ??= child._sortKey;
    _attributedLabel = _concatAttributedString(
      thisAttributedString: _attributedLabel,
      thisTextDirection: textDirection,
      otherAttributedString: child._attributedLabel,
      otherTextDirection: child.textDirection,
    );
    if (_attributedValue.string == '') {
      _attributedValue = child._attributedValue;
    }
    if (_attributedIncreasedValue.string == '') {
      _attributedIncreasedValue = child._attributedIncreasedValue;
    }
    if (_attributedDecreasedValue.string == '') {
      _attributedDecreasedValue = child._attributedDecreasedValue;
    }
    _attributedHint = _concatAttributedString(
      thisAttributedString: _attributedHint,
      thisTextDirection: textDirection,
      otherAttributedString: child._attributedHint,
      otherTextDirection: child.textDirection,
    );
    if (_tooltip == '') {
      _tooltip = child._tooltip;
    }

    _thickness = math.max(_thickness, child._thickness + child._elevation);

    _hasBeenAnnotated = _hasBeenAnnotated || child._hasBeenAnnotated;
  }

  /// Returns an exact copy of this configuration.
  SemanticsConfiguration copy() {
    return SemanticsConfiguration()
      .._isSemanticBoundary = _isSemanticBoundary
      ..explicitChildNodes = explicitChildNodes
      ..isBlockingSemanticsOfPreviouslyPaintedNodes = isBlockingSemanticsOfPreviouslyPaintedNodes
      .._hasBeenAnnotated = _hasBeenAnnotated
      .._isMergingSemanticsOfDescendants = _isMergingSemanticsOfDescendants
      .._textDirection = _textDirection
      .._sortKey = _sortKey
      .._attributedLabel = _attributedLabel
      .._attributedIncreasedValue = _attributedIncreasedValue
      .._attributedValue = _attributedValue
      .._attributedDecreasedValue = _attributedDecreasedValue
      .._attributedHint = _attributedHint
      .._hintOverrides = _hintOverrides
      .._tooltip = _tooltip
      .._elevation = _elevation
      .._thickness = _thickness
      .._flags = _flags
      .._tagsForChildren = _tagsForChildren
      .._textSelection = _textSelection
      .._scrollPosition = _scrollPosition
      .._scrollExtentMax = _scrollExtentMax
      .._scrollExtentMin = _scrollExtentMin
      .._actionsAsBits = _actionsAsBits
      .._indexInParent = indexInParent
      .._scrollIndex = _scrollIndex
      .._scrollChildCount = _scrollChildCount
      .._platformViewId = _platformViewId
      .._maxValueLength = _maxValueLength
      .._currentValueLength = _currentValueLength
      .._actions.addAll(_actions)
      .._customSemanticsActions.addAll(_customSemanticsActions)
      ..isBlockingUserActions = isBlockingUserActions;
  }
}

/// Used by [debugDumpSemanticsTree] to specify the order in which child nodes
/// are printed.
enum DebugSemanticsDumpOrder {
  /// Print nodes in inverse hit test order.
  ///
  /// In inverse hit test order, the last child of a [SemanticsNode] will be
  /// asked first if it wants to respond to a user's interaction, followed by
  /// the second last, etc. until a taker is found.
  inverseHitTest,

  /// Print nodes in semantic traversal order.
  ///
  /// This is the order in which a user would navigate the UI using the "next"
  /// and "previous" gestures.
  traversalOrder,
}

AttributedString _concatAttributedString({
  required AttributedString thisAttributedString,
  required AttributedString otherAttributedString,
  required TextDirection? thisTextDirection,
  required TextDirection? otherTextDirection,
}) {
  if (otherAttributedString.string.isEmpty) {
    return thisAttributedString;
  }
  if (thisTextDirection != otherTextDirection && otherTextDirection != null) {
    switch (otherTextDirection) {
      case TextDirection.rtl:
        otherAttributedString = AttributedString(Unicode.RLE) + otherAttributedString + AttributedString(Unicode.PDF);
      case TextDirection.ltr:
        otherAttributedString = AttributedString(Unicode.LRE) + otherAttributedString + AttributedString(Unicode.PDF);
    }
  }
  if (thisAttributedString.string.isEmpty) {
    return otherAttributedString;
  }

  return thisAttributedString + AttributedString('\n') + otherAttributedString;
}

/// Base class for all sort keys for [SemanticsProperties.sortKey] accessibility
/// traversal order sorting.
///
/// Sort keys are sorted by [name], then by the comparison that the subclass
/// implements. If [SemanticsProperties.sortKey] is specified, sort keys within
/// the same semantic group must all be of the same type.
///
/// Keys with no [name] are compared to other keys with no [name], and will
/// be traversed before those with a [name].
///
/// If no sort key is applied to a semantics node, then it will be ordered using
/// a platform dependent default algorithm.
///
/// See also:
///
///  * [OrdinalSortKey] for a sort key that sorts using an ordinal.
abstract class SemanticsSortKey with Diagnosticable implements Comparable<SemanticsSortKey> {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const SemanticsSortKey({this.name});

  /// An optional name that will group this sort key with other sort keys of the
  /// same [name].
  ///
  /// Sort keys must have the same `runtimeType` when compared.
  ///
  /// Keys with no [name] are compared to other keys with no [name], and will
  /// be traversed before those with a [name].
  final String? name;

  @override
  int compareTo(SemanticsSortKey other) {
    // Sort by name first and then subclass ordering.
    assert(runtimeType == other.runtimeType, 'Semantics sort keys can only be compared to other sort keys of the same type.');

    // Defer to the subclass implementation for ordering only if the names are
    // identical (or both null).
    if (name == other.name) {
      return doCompare(other);
    }

    // Keys that don't have a name are sorted together and come before those with
    // a name.
    if (name == null && other.name != null) {
      return -1;
    } else if (name != null && other.name == null) {
      return 1;
    }

    return name!.compareTo(other.name!);
  }

  /// The implementation of [compareTo].
  ///
  /// The argument is guaranteed to be of the same type as this object and have
  /// the same [name].
  ///
  /// The method should return a negative number if this object comes earlier in
  /// the sort order than the argument; and a positive number if it comes later
  /// in the sort order. Returning zero causes the system to use default sort
  /// order.
  @protected
  int doCompare(covariant SemanticsSortKey other);

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('name', name, defaultValue: null));
  }
}

/// A [SemanticsSortKey] that sorts based on the `double` value it is
/// given.
///
/// The [OrdinalSortKey] compares itself with other [OrdinalSortKey]s
/// to sort based on the order it is given.
///
/// [OrdinalSortKey]s are sorted by the optional [name], then by their [order].
/// If [SemanticsProperties.sortKey] is a [OrdinalSortKey], then all the other
/// specified sort keys in the same semantics group must also be
/// [OrdinalSortKey]s.
///
/// Keys with no [name] are compared to other keys with no [name], and will
/// be traversed before those with a [name].
///
/// The ordinal value [order] is typically a whole number, though it can be
/// fractional, e.g. in order to fit between two other consecutive whole
/// numbers. The value must be finite (it cannot be [double.nan],
/// [double.infinity], or [double.negativeInfinity]).
class OrdinalSortKey extends SemanticsSortKey {
  /// Creates a const semantics sort key that uses a [double] as its key value.
  ///
  /// The [order] must be a finite number, and must not be null.
  const OrdinalSortKey(
    this.order, {
    super.name,
  }) : assert(order > double.negativeInfinity),
       assert(order < double.infinity);

  /// Determines the placement of this key in a sequence of keys that defines
  /// the order in which this node is traversed by the platform's accessibility
  /// services.
  ///
  /// Lower values will be traversed first. Keys with the same [name] will be
  /// grouped together and sorted by name first, and then sorted by [order].
  final double order;

  @override
  int doCompare(OrdinalSortKey other) {
    if (other.order == order) {
      return 0;
    }
    return order.compareTo(other.order);
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DoubleProperty('order', order, defaultValue: null));
  }
}
