// 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.

/// @docImport 'package:flutter/material.dart';
///
/// @docImport 'widget_tester.dart';
library;

import 'dart:ui';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart' show Tooltip;
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

import 'binding.dart';
import 'tree_traversal.dart';

/// Signature for [CommonFinders.byWidgetPredicate].
typedef WidgetPredicate = bool Function(Widget widget);

/// Signature for [CommonFinders.byElementPredicate].
typedef ElementPredicate = bool Function(Element element);

/// Signature for [CommonSemanticsFinders.byPredicate].
typedef SemanticsNodePredicate = bool Function(SemanticsNode node);

/// Signature for [FinderBase.describeMatch].
typedef DescribeMatchCallback = String Function(Plurality plurality);

/// Returns true if [renderObject] is equal to [target] or is an ancestor of
/// [target] in the render tree.
///
/// This is useful for hit testing because some render objects (like
/// [RenderTransform]) don't add themselves to the hit test path but instead
/// just transform the hit test point and pass it to their children.
bool isRenderObjectAncestorOfTarget(RenderObject renderObject, HitTestTarget target) {
  if (target == renderObject) {
    return true;
  }
  if (target is RenderObject) {
    for (RenderObject? current = target.parent; current != null; current = current.parent) {
      if (current == renderObject) {
        return true;
      }
    }
  }
  return false;
}

/// The `CandidateType` of finders that search for and filter substrings,
/// within static text rendered by [RenderParagraph]s.
final class TextRangeContext {
  const TextRangeContext._(this.view, this.renderObject, this.textRange);

  /// The [View] containing the static text.
  ///
  /// This is used for hit-testing.
  final View view;

  /// The RenderObject that contains the static text.
  final RenderParagraph renderObject;

  /// The [TextRange] of the substring within [renderObject]'s text.
  final TextRange textRange;

  @override
  String toString() => 'TextRangeContext($view, $renderObject, $textRange)';
}

/// Some frequently used [Finder]s and [SemanticsFinder]s.
const CommonFinders find = CommonFinders._();

// Examples can assume:
// typedef Button = Placeholder;
// late WidgetTester tester;
// late String filePath;
// late Key backKey;

/// Provides lightweight syntax for getting frequently used [Finder]s and
/// [SemanticsFinder]s through [semantics].
///
/// This class is instantiated once, as [find].
class CommonFinders {
  const CommonFinders._();

  /// Some frequently used semantics finders.
  CommonSemanticsFinders get semantics => const CommonSemanticsFinders._();

  /// Some frequently used text range finders.
  CommonTextRangeFinders get textRange => const CommonTextRangeFinders._();

  /// Finds [Text], [EditableText], and optionally [RichText] widgets
  /// containing string equal to the `text` argument.
  ///
  /// If `findRichText` is false, all standalone [RichText] widgets are
  /// ignored and `text` is matched with [Text.data] or [Text.textSpan].
  /// If `findRichText` is true, [RichText] widgets (and therefore also
  /// [Text] and [Text.rich] widgets) are matched by comparing the
  /// [InlineSpan.toPlainText] with the given `text`.
  ///
  /// For [EditableText] widgets, the `text` is always compared to the current
  /// value of the [EditableText.controller].
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.text('Back'), findsOneWidget);
  /// ```
  ///
  /// This will match [Text], [Text.rich], and [EditableText] widgets that
  /// contain the "Back" string.
  ///
  /// ```dart
  /// expect(find.text('Close', findRichText: true), findsOneWidget);
  /// ```
  ///
  /// This will match [Text], [Text.rich], [EditableText], as well as standalone
  /// [RichText] widgets that contain the "Close" string.
  Finder text(String text, {bool findRichText = false, bool skipOffstage = true}) {
    return _TextWidgetFinder(text, findRichText: findRichText, skipOffstage: skipOffstage);
  }

  /// Finds [Text] and [EditableText], and optionally [RichText] widgets
  /// which contain the given `pattern` argument.
  ///
  /// If `findRichText` is false, all standalone [RichText] widgets are
  /// ignored and `pattern` is matched with [Text.data] or [Text.textSpan].
  /// If `findRichText` is true, [RichText] widgets (and therefore also
  /// [Text] and [Text.rich] widgets) are matched by comparing the
  /// [InlineSpan.toPlainText] with the given `pattern`.
  ///
  /// For [EditableText] widgets, the `pattern` is always compared to the current
  /// value of the [EditableText.controller].
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.textContaining('Back'), findsOneWidget);
  /// expect(find.textContaining(RegExp(r'(\w+)')), findsOneWidget);
  /// ```
  ///
  /// This will match [Text], [Text.rich], and [EditableText] widgets that
  /// contain the given pattern : 'Back' or RegExp(r'(\w+)').
  ///
  /// ```dart
  /// expect(find.textContaining('Close', findRichText: true), findsOneWidget);
  /// expect(find.textContaining(RegExp(r'(\w+)'), findRichText: true), findsOneWidget);
  /// ```
  ///
  /// This will match [Text], [Text.rich], [EditableText], as well as standalone
  /// [RichText] widgets that contain the given pattern : 'Close' or RegExp(r'(\w+)').
  Finder textContaining(Pattern pattern, {bool findRichText = false, bool skipOffstage = true}) {
    return _TextContainingWidgetFinder(
      pattern,
      findRichText: findRichText,
      skipOffstage: skipOffstage,
    );
  }

  /// Looks for widgets that contain a [Text] descendant with `text`
  /// in it.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// // Suppose there is a button with text 'Update' in it:
  /// const Button(
  ///   child: Text('Update')
  /// );
  ///
  /// // It can be found and tapped like this:
  /// tester.tap(find.widgetWithText(Button, 'Update'));
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder widgetWithText(Type widgetType, String text, {bool skipOffstage = true}) {
    return find.ancestor(
      of: find.text(text, skipOffstage: skipOffstage),
      matching: find.byType(widgetType, skipOffstage: skipOffstage),
    );
  }

  /// Finds [Image] and [FadeInImage] widgets containing `image` equal to the
  /// `image` argument.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.image(FileImage(File(filePath))), findsOneWidget);
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder image(ImageProvider image, {bool skipOffstage = true}) =>
      _ImageWidgetFinder(image, skipOffstage: skipOffstage);

  /// Finds widgets by searching for one with the given `key`.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.byKey(backKey), findsOneWidget);
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder byKey(Key key, {bool skipOffstage = true}) =>
      _KeyWidgetFinder(key, skipOffstage: skipOffstage);

  /// Finds widgets by searching for widgets implementing a particular type.
  ///
  /// This matcher accepts subtypes. For example a
  /// `bySubtype<StatefulWidget>()` will find any stateful widget.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.bySubtype<IconButton>(), findsOneWidget);
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  ///
  /// See also:
  /// * [byType], which does not do subtype tests.
  Finder bySubtype<T extends Widget>({bool skipOffstage = true}) =>
      _SubtypeWidgetFinder<T>(skipOffstage: skipOffstage);

  /// Finds widgets by searching for widgets with a particular type.
  ///
  /// This does not do subclass tests, so for example
  /// `byType(StatefulWidget)` will never find anything since [StatefulWidget]
  /// is an abstract class.
  ///
  /// The `type` argument must be a subclass of [Widget].
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.byType(IconButton), findsOneWidget);
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  ///
  /// See also:
  /// * [bySubtype], which allows subtype tests.
  Finder byType(Type type, {bool skipOffstage = true}) =>
      _TypeWidgetFinder(type, skipOffstage: skipOffstage);

  /// Finds [Icon] widgets containing icon data equal to the `icon`
  /// argument.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.byIcon(Icons.inbox), findsOneWidget);
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder byIcon(IconData icon, {bool skipOffstage = true}) =>
      _IconWidgetFinder(icon, skipOffstage: skipOffstage);

  /// Looks for widgets that contain an [Icon] descendant displaying [IconData]
  /// `icon` in it.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// // Suppose there is a button with icon 'arrow_forward' in it:
  /// const Button(
  ///   child: Icon(Icons.arrow_forward)
  /// );
  ///
  /// // It can be found and tapped like this:
  /// tester.tap(find.widgetWithIcon(Button, Icons.arrow_forward));
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder widgetWithIcon(Type widgetType, IconData icon, {bool skipOffstage = true}) {
    return find.ancestor(of: find.byIcon(icon), matching: find.byType(widgetType));
  }

  /// Looks for widgets that contain an [Image] descendant displaying
  /// [ImageProvider] `image` in it.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// // Suppose there is a button with an image in it:
  /// Button(
  ///   child: Image.file(File(filePath))
  /// );
  ///
  /// // It can be found and tapped like this:
  /// tester.tap(find.widgetWithImage(Button, FileImage(File(filePath))));
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder widgetWithImage(Type widgetType, ImageProvider image, {bool skipOffstage = true}) {
    return find.ancestor(of: find.image(image), matching: find.byType(widgetType));
  }

  /// Finds widgets by searching for elements with a particular type.
  ///
  /// This does not do subclass tests, so for example
  /// `byElementType(VirtualViewportElement)` will never find anything
  /// since [RenderObjectElement] is an abstract class.
  ///
  /// The `type` argument must be a subclass of [Element].
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.byElementType(SingleChildRenderObjectElement), findsOneWidget);
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder byElementType(Type type, {bool skipOffstage = true}) =>
      _ElementTypeWidgetFinder(type, skipOffstage: skipOffstage);

  /// Finds widgets whose current widget is the instance given by the `widget`
  /// argument.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// // Suppose there is a button created like this:
  /// Widget myButton = const Button(
  ///   child: Text('Update')
  /// );
  ///
  /// // It can be found and tapped like this:
  /// tester.tap(find.byWidget(myButton));
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder byWidget(Widget widget, {bool skipOffstage = true}) =>
      _ExactWidgetFinder(widget, skipOffstage: skipOffstage);

  /// Finds widgets using a widget `predicate`.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.byWidgetPredicate(
  ///   (Widget widget) => widget is Tooltip && widget.message == 'Back',
  ///   description: 'with tooltip "Back"',
  /// ), findsOneWidget);
  /// ```
  ///
  /// If `description` is provided, then this uses it as the description of the
  /// [Finder] and appears, for example, in the error message when the finder
  /// fails to locate the desired widget. Otherwise, the description prints the
  /// signature of the predicate function.
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder byWidgetPredicate(
    WidgetPredicate predicate, {
    String? description,
    bool skipOffstage = true,
  }) {
    return _WidgetPredicateWidgetFinder(
      predicate,
      description: description,
      skipOffstage: skipOffstage,
    );
  }

  /// Finds [RawTooltip] or [Tooltip] widgets with the given `message`.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.byTooltip('Back'), findsOneWidget);
  /// expect(find.byTooltip(RegExp('Back.*')), findsNWidgets(2));
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder byTooltip(Pattern message, {bool skipOffstage = true}) {
    return byWidgetPredicate((Widget widget) {
      // Compare RawTooltip's semantics tooltip with the given message.
      // However, Tooltip's message needs to be checked directly if:
      // 1. Tooltip.excludeFromSemantics is true, since in this case Tooltip
      //    provides no semantics tooltip to the underlying RawTooltip.
      // 2. Tooltip.message and Tooltip.richMessage are empty, since in this
      //    case no RawTooltip is created.
      if (widget is Tooltip) {
        final String tooltipMessage = widget.message ?? widget.richMessage!.toPlainText();
        if ((widget.excludeFromSemantics ?? false) || tooltipMessage.isEmpty) {
          return message is RegExp ? message.hasMatch(tooltipMessage) : tooltipMessage == message;
        }
      }
      return widget is RawTooltip &&
          (message is RegExp
              ? message.hasMatch(widget.semanticsTooltip ?? '')
              : widget.semanticsTooltip == message);
    }, skipOffstage: skipOffstage);
  }

  /// Finds widgets using an element `predicate`.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.byElementPredicate(
  ///   // Finds elements of type SingleChildRenderObjectElement, including
  ///   // those that are actually subclasses of that type.
  ///   // (contrast with byElementType, which only returns exact matches)
  ///   (Element element) => element is SingleChildRenderObjectElement,
  ///   description: '$SingleChildRenderObjectElement element',
  /// ), findsOneWidget);
  /// ```
  ///
  /// If `description` is provided, then this uses it as the description of the
  /// [Finder] and appears, for example, in the error message when the finder
  /// fails to locate the desired widget. Otherwise, the description prints the
  /// signature of the predicate function.
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder byElementPredicate(
    ElementPredicate predicate, {
    String? description,
    bool skipOffstage = true,
  }) {
    return _ElementPredicateWidgetFinder(
      predicate,
      description: description,
      skipOffstage: skipOffstage,
    );
  }

  /// Finds widgets that are descendants of the `of` parameter and that match
  /// the `matching` parameter.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.descendant(
  ///   of: find.widgetWithText(Row, 'label_1'),
  ///   matching: find.text('value_1'),
  /// ), findsOneWidget);
  /// ```
  ///
  /// If the `matchRoot` argument is true then the widget(s) specified by `of`
  /// will be matched along with the descendants.
  ///
  /// If the `skipOffstage` argument is true (the default), then nodes that are
  /// [Offstage] or that are from inactive [Route]s are skipped.
  Finder descendant({
    required FinderBase<Element> of,
    required FinderBase<Element> matching,
    bool matchRoot = false,
    bool skipOffstage = true,
  }) {
    return _DescendantWidgetFinder(of, matching, matchRoot: matchRoot, skipOffstage: skipOffstage);
  }

  /// Finds widgets that are ancestors of the `of` parameter and that match
  /// the `matching` parameter.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// // Test if a Text widget that contains 'faded' is the
  /// // descendant of an Opacity widget with opacity 0.5:
  /// expect(
  ///   tester.widget<Opacity>(
  ///     find.ancestor(
  ///       of: find.text('faded'),
  ///       matching: find.byType(Opacity),
  ///     )
  ///   ).opacity,
  ///   0.5
  /// );
  /// ```
  ///
  /// If the `matchRoot` argument is true then the widget(s) specified by `of`
  /// will be matched along with the ancestors.
  Finder ancestor({
    required FinderBase<Element> of,
    required FinderBase<Element> matching,
    bool matchRoot = false,
  }) {
    return _AncestorWidgetFinder(of, matching, matchLeaves: matchRoot);
  }

  /// Finds a standard "back" button.
  ///
  /// A common element on many user interfaces is the "back" button. This is
  /// the button which takes the user back to the previous page/screen/state.
  ///
  /// It is useful in tests to be able to find these buttons, both for tapping
  /// them or verifying their existence, but because different platforms and
  /// locales have different icons representing them with different labels and
  /// tooltips, it's not desirable to have to look them up by these attributes.
  ///
  /// This finder uses the [StandardComponentType] enum to look for buttons that
  /// have the key associated with [StandardComponentType.backButton]. If
  /// another widget is assigned that key, then it too will be considered an
  /// "official" back button in the widget tree, allowing this matcher to still
  /// find it even though it might use a different icon or tooltip.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.backButton(), findsOneWidget);
  /// ```
  ///
  /// See also:
  ///
  /// * [StandardComponentType], the enum that enumerates components that are
  ///   both common in user interfaces, but which also can vary slightly in
  ///   presentation across different platforms, locales, and devices.
  /// * [BackButton], the Flutter Material widget that represents the back
  ///   button.
  Finder backButton() {
    return byKey(StandardComponentType.backButton.key);
  }

  /// Finds a standard "close" button.
  ///
  /// A common element on many user interfaces is the "close" button. This is
  /// the button which closes or cancels whatever it is attached to.
  ///
  /// It is useful in tests to be able to find these buttons, both for tapping
  /// them or verifying their existence, but because different platforms and
  /// locales have different icons representing them with different labels and
  /// tooltips, it's not desirable to have to look them up by these attributes.
  ///
  /// This finder uses the [StandardComponentType] enum to look for buttons that
  /// have the key associated with [StandardComponentType.closeButton]. If
  /// another widget is assigned that key, then it too will be considered an
  /// "official" close button in the widget tree, allowing this matcher to still
  /// find it even though it might use a different icon or tooltip.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.closeButton(), findsOneWidget);
  /// ```
  ///
  /// See also:
  ///
  /// * [StandardComponentType], the enum that enumerates components that are
  ///   both common in user interfaces, but which also can vary slightly in
  ///   presentation across different platforms, locales, and devices.
  /// * [CloseButton], the Flutter Material widget that represents a close
  ///   button.
  Finder closeButton() {
    return byKey(StandardComponentType.closeButton.key);
  }

  /// Finds [Semantics] widgets matching the given `label`, either by
  /// [RegExp.hasMatch] or string equality.
  ///
  /// The framework may combine semantics labels in certain scenarios, such as
  /// when multiple [Text] widgets are in a [TextButton] widget. In such a
  /// case, it may be preferable to match by regular expression. Consumers of
  /// this API __must not__ introduce unsuitable content into the semantics tree
  /// for the purposes of testing; in particular, you should prefer matching by
  /// regular expression rather than by string if the framework has combined
  /// your semantics, and not try to force the framework to break up the
  /// semantics nodes. Breaking up the nodes would have an undesirable effect on
  /// screen readers and other accessibility services.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.bySemanticsLabel('Back'), findsOneWidget);
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder bySemanticsLabel(Pattern label, {bool skipOffstage = true}) {
    final String description = switch (label) {
      final RegExp regExp => 'a semantics label matching the pattern "${regExp.pattern}"',
      final String labelString => 'a semantics label named "$labelString"',
      _ => 'a semantics label matching "$label"',
    };

    return _bySemanticsProperty(
      label,
      description,
      (SemanticsNode? semantics) => semantics?.label,
      skipOffstage: skipOffstage,
    );
  }

  /// Finds [Semantics] widgets matching the given `identifier`, either by
  /// [RegExp.hasMatch] or string equality.
  ///
  /// This allows matching against the identifier of a [Semantics] widget, which
  /// is a unique identifier for the widget in the semantics tree. This is
  /// exposed to offer a unified way widget tests and e2e tests can match
  /// against a [Semantics] widget.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// expect(find.bySemanticsIdentifier('Back'), findsOneWidget);
  /// ```
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// nodes that are [Offstage] or that are from inactive [Route]s.
  Finder bySemanticsIdentifier(Pattern identifier, {bool skipOffstage = true}) {
    final String description = switch (identifier) {
      final RegExp regExp => 'a semantics identifier matching the pattern "${regExp.pattern}"',
      final String id => 'a semantics identifier named "$id"',
      _ => 'a semantics identifier matching "$identifier"',
    };

    return _bySemanticsProperty(
      identifier,
      description,
      (SemanticsNode? semantics) => semantics?.identifier,
      skipOffstage: skipOffstage,
    );
  }

  Finder _bySemanticsProperty(
    Pattern pattern,
    String description,
    String? Function(SemanticsNode?) propertyGetter, {
    bool skipOffstage = true,
  }) {
    if (!SemanticsBinding.instance.semanticsEnabled) {
      throw StateError(
        'Semantics are not enabled. '
        'Make sure to call tester.ensureSemantics() before using '
        'this finder, and call dispose on its return value after.',
      );
    }

    return byElementPredicate(
      (Element element) {
        // Multiple elements can have the same renderObject - we want the "owner"
        // of the renderObject, i.e. the RenderObjectElement.
        if (element is! RenderObjectElement) {
          return false;
        }
        final String? propertyValue = propertyGetter(element.renderObject.debugSemantics);
        if (propertyValue == null) {
          return false;
        }
        return pattern is RegExp ? pattern.hasMatch(propertyValue) : pattern == propertyValue;
      },
      description: description,
      skipOffstage: skipOffstage,
    );
  }
}

/// Provides lightweight syntax for getting frequently used semantics finders.
///
/// This class is instantiated once, as [CommonFinders.semantics], under [find].
class CommonSemanticsFinders {
  const CommonSemanticsFinders._();

  /// Finds an ancestor of `of` that matches `matching`.
  ///
  /// If `matchRoot` is true, then the results of `of` are included in the
  /// search and results.
  FinderBase<SemanticsNode> ancestor({
    required FinderBase<SemanticsNode> of,
    required FinderBase<SemanticsNode> matching,
    bool matchRoot = false,
  }) {
    return _AncestorSemanticsFinder(of, matching, matchRoot);
  }

  /// Finds a descendant of `of` that matches `matching`.
  ///
  /// If `matchRoot` is true, then the results of `of` are included in the
  /// search and results.
  FinderBase<SemanticsNode> descendant({
    required FinderBase<SemanticsNode> of,
    required FinderBase<SemanticsNode> matching,
    bool matchRoot = false,
  }) {
    return _DescendantSemanticsFinder(of, matching, matchRoot: matchRoot);
  }

  /// Finds any [SemanticsNode]s matching the given `predicate`.
  ///
  /// If `describeMatch` is provided, it will be used to describe the
  /// [FinderBase] and [FinderResult]s.
  /// {@macro flutter_test.finders.FinderBase.describeMatch}
  ///
  /// {@template flutter_test.finders.CommonSemanticsFinders.viewParameter}
  /// The `view` provided will be used to determine the semantics tree where
  /// the search will be evaluated. If not provided, the search will be
  /// evaluated against the semantics tree of [WidgetTester.view].
  /// {@endtemplate}
  SemanticsFinder byPredicate(
    SemanticsNodePredicate predicate, {
    DescribeMatchCallback? describeMatch,
    FlutterView? view,
  }) {
    return _PredicateSemanticsFinder(predicate, describeMatch, view);
  }

  /// Finds any [SemanticsNode]s that has a [SemanticsNode.label] that matches
  /// the given `label`.
  ///
  /// {@macro flutter_test.finders.CommonSemanticsFinders.viewParameter}
  SemanticsFinder byLabel(Pattern label, {FlutterView? view}) {
    return byPredicate(
      (SemanticsNode node) => _matchesPattern(node.label, label),
      describeMatch: (Plurality plurality) =>
          '${switch (plurality) {
            Plurality.one => 'SemanticsNode',
            Plurality.zero || Plurality.many => 'SemanticsNodes',
          }} with label "$label"',
      view: view,
    );
  }

  /// Finds any [SemanticsNode]s that has a [SemanticsNode.value] that matches
  /// the given `value`.
  ///
  /// {@macro flutter_test.finders.CommonSemanticsFinders.viewParameter}
  SemanticsFinder byValue(Pattern value, {FlutterView? view}) {
    return byPredicate(
      (SemanticsNode node) => _matchesPattern(node.value, value),
      describeMatch: (Plurality plurality) =>
          '${switch (plurality) {
            Plurality.one => 'SemanticsNode',
            Plurality.zero || Plurality.many => 'SemanticsNodes',
          }} with value "$value"',
      view: view,
    );
  }

  /// Finds any [SemanticsNode]s that has a [SemanticsNode.hint] that matches
  /// the given `hint`.
  ///
  /// {@macro flutter_test.finders.CommonSemanticsFinders.viewParameter}
  SemanticsFinder byHint(Pattern hint, {FlutterView? view}) {
    return byPredicate(
      (SemanticsNode node) => _matchesPattern(node.hint, hint),
      describeMatch: (Plurality plurality) =>
          '${switch (plurality) {
            Plurality.one => 'SemanticsNode',
            Plurality.zero || Plurality.many => 'SemanticsNodes',
          }} with hint "$hint"',
      view: view,
    );
  }

  /// Finds any [SemanticsNode]s that has the given [SemanticsAction].
  ///
  /// {@macro flutter_test.finders.CommonSemanticsFinders.viewParameter}
  SemanticsFinder byAction(SemanticsAction action, {FlutterView? view}) {
    return byPredicate(
      (SemanticsNode node) => node.getSemanticsData().hasAction(action),
      describeMatch: (Plurality plurality) =>
          '${switch (plurality) {
            Plurality.one => 'SemanticsNode',
            Plurality.zero || Plurality.many => 'SemanticsNodes',
          }} with action "$action"',
      view: view,
    );
  }

  /// Finds any [SemanticsNode]s that has at least one of the given
  /// [SemanticsAction]s.
  ///
  /// {@macro flutter_test.finders.CommonSemanticsFinders.viewParameter}
  SemanticsFinder byAnyAction(List<SemanticsAction> actions, {FlutterView? view}) {
    final int actionsInt = actions.fold(
      0,
      (int value, SemanticsAction action) => value | action.index,
    );
    return byPredicate(
      (SemanticsNode node) => node.getSemanticsData().actions & actionsInt != 0,
      describeMatch: (Plurality plurality) =>
          '${switch (plurality) {
            Plurality.one => 'SemanticsNode',
            Plurality.zero || Plurality.many => 'SemanticsNodes',
          }} with any of the following actions: $actions',
      view: view,
    );
  }

  /// Finds any [SemanticsNode]s that has the given [SemanticsFlag].
  ///
  /// {@macro flutter_test.finders.CommonSemanticsFinders.viewParameter}
  SemanticsFinder byFlag(SemanticsFlag flag, {FlutterView? view}) {
    return byPredicate(
      (SemanticsNode node) => node.hasFlag(flag),
      describeMatch: (Plurality plurality) =>
          '${switch (plurality) {
            Plurality.one => 'SemanticsNode',
            Plurality.zero || Plurality.many => 'SemanticsNodes',
          }} with flag "$flag"',
      view: view,
    );
  }

  /// Finds any [SemanticsNode]s that has at least one of the given
  /// [SemanticsFlag]s.
  ///
  /// {@macro flutter_test.finders.CommonSemanticsFinders.viewParameter}
  SemanticsFinder byAnyFlag(List<SemanticsFlag> flags, {FlutterView? view}) {
    final int flagsInt = flags.fold(0, (int value, SemanticsFlag flag) => value | flag.index);
    return byPredicate(
      (SemanticsNode node) => node.getSemanticsData().flags & flagsInt != 0,
      describeMatch: (Plurality plurality) =>
          '${switch (plurality) {
            Plurality.one => 'SemanticsNode',
            Plurality.zero || Plurality.many => 'SemanticsNodes',
          }} with any of the following flags: $flags',
      view: view,
    );
  }

  /// Finds any [SemanticsNode]s that can scroll in at least one direction.
  ///
  /// If `axis` is provided, then the search will be limited to scrollable nodes
  /// that can scroll in the given axis. If `axis` is not provided, then both
  /// horizontal and vertical scrollable nodes will be found.
  ///
  /// {@macro flutter_test.finders.CommonSemanticsFinders.viewParameter}
  SemanticsFinder scrollable({Axis? axis, FlutterView? view}) {
    return byAnyAction(<SemanticsAction>[
      if (axis == null || axis == Axis.vertical) ...<SemanticsAction>[
        SemanticsAction.scrollUp,
        SemanticsAction.scrollDown,
      ],
      if (axis == null || axis == Axis.horizontal) ...<SemanticsAction>[
        SemanticsAction.scrollLeft,
        SemanticsAction.scrollRight,
      ],
    ]);
  }

  bool _matchesPattern(String target, Pattern pattern) {
    if (pattern is RegExp) {
      return pattern.hasMatch(target);
    } else {
      return pattern == target;
    }
  }
}

/// Provides lightweight syntax for getting frequently used text range finders.
///
/// This class is instantiated once, as [CommonFinders.textRange], under [find].
final class CommonTextRangeFinders {
  const CommonTextRangeFinders._();

  /// Finds all non-overlapping occurrences of the given `substring` in the
  /// static text widgets and returns the [TextRange]s.
  ///
  /// If the `skipOffstage` argument is true (the default), then this skips
  /// static text inside widgets that are [Offstage], or that are from inactive
  /// [Route]s.
  ///
  /// If the `descendentOf` argument is non-null, this method only searches in
  /// the descendants of that parameter for the given substring.
  ///
  /// This finder uses the [Pattern.allMatches] method to match the substring in
  /// the text. After finding a matching substring in the text, the method
  /// continues the search from the end of the match, thus skipping overlapping
  /// occurrences of the substring.
  FinderBase<TextRangeContext> ofSubstring(
    String substring, {
    bool skipOffstage = true,
    FinderBase<Element>? descendentOf,
  }) {
    final textWidgetFinder = _TextContainingWidgetFinder(
      substring,
      skipOffstage: skipOffstage,
      findRichText: true,
    );
    final Finder elementFinder = descendentOf == null
        ? textWidgetFinder
        : _DescendantWidgetFinder(
            descendentOf,
            textWidgetFinder,
            matchRoot: true,
            skipOffstage: skipOffstage,
          );
    return _StaticTextRangeFinder(elementFinder, substring);
  }
}

/// Describes how a string of text should be pluralized.
enum Plurality {
  /// Text should be pluralized to describe zero items.
  zero,

  /// Text should be pluralized to describe a single item.
  one,

  /// Text should be pluralized to describe more than one item.
  many;

  static Plurality _fromNum(num source) {
    assert(source >= 0, 'A Plurality can only be created with a positive number.');
    return switch (source) {
      0 => Plurality.zero,
      1 => Plurality.one,
      _ => Plurality.many,
    };
  }
}

/// Encapsulates the logic for searching a list of candidates and filtering the
/// candidates to only those that meet the requirements defined by the finder.
///
/// Implementations will need to implement [allCandidates] to define the total
/// possible search space and [findInCandidates] to define the requirements of
/// the finder.
///
/// This library contains [Finder] and [SemanticsFinder] for searching
/// Flutter's element and semantics trees respectively.
///
/// If the search can be represented as a predicate, then consider using
/// [MatchFinderMixin] along with the [Finder] or [SemanticsFinder] base class.
///
/// If the search further filters the results from another finder, consider using
/// [ChainedFinderMixin] along with the [Finder] or [SemanticsFinder] base class.
abstract class FinderBase<CandidateType> {
  bool _cached = false;

  /// The results of the latest [evaluate] or [tryEvaluate] call.
  ///
  /// Unlike [evaluate] and [tryEvaluate], [found] will not re-execute the
  /// search for this finder. Either [evaluate] or [tryEvaluate] must be called
  /// before accessing [found].
  FinderResult<CandidateType> get found {
    assert(
      _found != null,
      'No results have been found yet. '
      'Either `evaluate` or `tryEvaluate` must be called before accessing `found`',
    );
    return _found!;
  }

  FinderResult<CandidateType>? _found;

  /// Whether or not this finder has any results in [found].
  bool get hasFound => _found != null;

  /// Describes zero, one, or more candidates that match the requirements of a
  /// finder.
  ///
  /// {@template flutter_test.finders.FinderBase.describeMatch}
  /// The description returned should be a brief English phrase describing a
  /// matching candidate with the proper plural form. As an example for a string
  /// finder that is looking for strings starting with "hello":
  ///
  /// ```dart
  /// String describeMatch(Plurality plurality) {
  ///   return switch (plurality) {
  ///     Plurality.zero || Plurality.many => 'strings starting with "hello"',
  ///     Plurality.one => 'string starting with "hello"',
  ///   };
  /// }
  /// ```
  /// {@endtemplate}
  ///
  /// This will be used both to describe a finder and the results of searching
  /// with that finder.
  ///
  /// See also:
  ///
  ///   * [FinderBase.toString] where this is used to fully describe the finder
  ///   * [FinderResult.toString] where this is used to provide context to the
  ///     results of a search
  String describeMatch(Plurality plurality);

  /// Returns all of the items that will be considered by this finder.
  @protected
  Iterable<CandidateType> get allCandidates;

  /// Returns a variant of this finder that only matches the first item
  /// found by this finder.
  FinderBase<CandidateType> get first => _FirstFinder<CandidateType>(this);

  /// Returns a variant of this finder that only matches the last item
  /// found by this finder.
  FinderBase<CandidateType> get last => _LastFinder<CandidateType>(this);

  /// Returns a variant of this finder that only matches the item at the
  /// given index found by this finder.
  FinderBase<CandidateType> at(int index) => _IndexFinder<CandidateType>(this, index);

  /// Returns all the items in the given list that match this
  /// finder's requirements.
  ///
  /// This is overridden to define the requirements of the finder when
  /// implementing finders that directly extend [FinderBase]. If a finder can
  /// be efficiently described just in terms of a predicate function, consider
  /// mixing in [MatchFinderMixin] and implementing [MatchFinderMixin.matches]
  /// instead.
  @protected
  Iterable<CandidateType> findInCandidates(Iterable<CandidateType> candidates);

  /// Searches a set of candidates for those that meet the requirements set by
  /// this finder and returns the result of that search.
  ///
  /// See also:
  ///
  ///   * [found] which will return the latest results without re-executing the
  ///     search.
  ///   * [tryEvaluate] which will indicate whether any results were found rather
  ///     than directly returning results.
  FinderResult<CandidateType> evaluate() {
    if (!_cached || _found == null) {
      _found = FinderResult<CandidateType>(describeMatch, findInCandidates(allCandidates));
    }
    return found;
  }

  /// Searches a set of candidates for those that meet the requirements set by
  /// this finder and returns whether the search found any matching candidates.
  ///
  /// This is useful in cases where an action needs to be repeated while or
  /// until a finder has results. The results from the search can be accessed
  /// using the [found] property without re-executing the search.
  ///
  /// ## Sample code
  ///
  /// ```dart
  /// testWidgets('Top text loads first', (WidgetTester tester) async {
  ///   // Assume a widget is pumped with a top and bottom loading area, with
  ///   // the texts "Top loaded" and "Bottom loaded" when loading is complete.
  ///   // await tester.pumpWidget(...)
  ///
  ///   // Wait until at least one loaded widget is available
  ///   Finder loadedFinder = find.textContaining('loaded');
  ///   while (!loadedFinder.tryEvaluate()) {
  ///     await tester.pump(const Duration(milliseconds: 100));
  ///   }
  ///
  ///   expect(loadedFinder.found, hasLength(1));
  ///   expect(tester.widget<Text>(loadedFinder).data, contains('Top'));
  /// });
  /// ```
  bool tryEvaluate() {
    evaluate();
    return found.isNotEmpty;
  }

  /// Runs the given callback using cached results.
  ///
  /// While in this callback, this [FinderBase] will cache the results from the
  /// next call to [evaluate] or [tryEvaluate] and then no longer evaluate new results
  /// until the callback completes. After the first call, all calls to [evaluate],
  /// [tryEvaluate] or [found] will return the same results without evaluating.
  void runCached(VoidCallback run) {
    reset();
    _cached = true;
    try {
      run();
    } finally {
      reset();
      _cached = false;
    }
  }

  /// Resets all state of this [FinderBase].
  ///
  /// Generally used between tests to reset the state of [found] if a finder is
  /// used across multiple tests.
  void reset() {
    _found = null;
  }

  /// A string representation of this finder or its results.
  ///
  /// By default, this describes the results of the search in order to play
  /// nicely with [expect] and its output when a failure occurs. If you wish
  /// to get a string representation of the finder itself, pass [describeSelf]
  /// as `true`.
  @override
  String toString({bool describeSelf = false}) {
    if (describeSelf) {
      return 'A finder that searches for ${describeMatch(Plurality.many)}.';
    } else {
      if (!hasFound) {
        evaluate();
      }
      return found.toString();
    }
  }
}

/// The results of searching with a [FinderBase].
class FinderResult<CandidateType> extends Iterable<CandidateType> {
  /// Creates a new [FinderResult] that describes the `values` using the given
  /// `describeMatch` callback.
  ///
  /// {@macro flutter_test.finders.FinderBase.describeMatch}
  FinderResult(DescribeMatchCallback describeMatch, Iterable<CandidateType> values)
    : _describeMatch = describeMatch,
      _values = values;

  final DescribeMatchCallback _describeMatch;
  final Iterable<CandidateType> _values;

  @override
  Iterator<CandidateType> get iterator => _values.iterator;

  @override
  String toString() {
    final List<CandidateType> valuesList = _values.toList();
    // This will put each value on its own line with a comma and indentation
    final String valuesString = valuesList.fold(
      '',
      (String current, CandidateType candidate) => '$current\n  $candidate,',
    );
    return 'Found ${valuesList.length} ${_describeMatch(Plurality._fromNum(valuesList.length))}: ['
        '${valuesString.isNotEmpty ? '$valuesString\n' : ''}'
        ']';
  }
}

/// Provides backwards compatibility with the original [Finder] API.
mixin _LegacyFinderMixin on FinderBase<Element> {
  Iterable<Element>? _precacheResults;

  /// Describes what the finder is looking for. The description should be
  /// a brief English noun phrase describing the finder's requirements.
  @Deprecated(
    'Use FinderBase.describeMatch instead. '
    'FinderBase.describeMatch allows for more readable descriptions and removes ambiguity about pluralization. '
    'This feature was deprecated after v3.13.0-0.2.pre.',
  )
  String get description;

  /// Returns all the elements in the given list that match this
  /// finder's pattern.
  ///
  /// When implementing Finders that inherit directly from
  /// [Finder], [findInCandidates] is the main method to override. This method
  /// is maintained for backwards compatibility and will be removed in a future
  /// version of Flutter. If the finder can efficiently be described just in
  /// terms of a predicate function, consider mixing in [MatchFinderMixin]
  /// instead.
  @Deprecated(
    'Override FinderBase.findInCandidates instead. '
    'Using the FinderBase API allows for more consistent caching behavior and cleaner options for interacting with the widget tree. '
    'This feature was deprecated after v3.13.0-0.2.pre.',
  )
  Iterable<Element> apply(Iterable<Element> candidates) {
    return findInCandidates(candidates);
  }

  /// Attempts to evaluate the finder. Returns whether any elements in the tree
  /// matched the finder. If any did, then the result is cached and can be obtained
  /// from [evaluate].
  ///
  /// If this returns true, you must call [evaluate] before you call [precache] again.
  @Deprecated(
    'Use FinderBase.tryFind or FinderBase.runCached instead. '
    'Using the FinderBase API allows for more consistent caching behavior and cleaner options for interacting with the widget tree. '
    'This feature was deprecated after v3.13.0-0.2.pre.',
  )
  bool precache() {
    assert(_precacheResults == null);
    if (tryEvaluate()) {
      return true;
    }
    _precacheResults = null;
    return false;
  }

  @override
  Iterable<Element> findInCandidates(Iterable<Element> candidates) {
    return apply(candidates);
  }
}

/// A base class for creating finders that search the [Element] tree for
/// [Widget]s.
///
/// The [findInCandidates] method must be overridden and will be enforced at
/// compilation after [apply] is removed.
abstract class Finder extends FinderBase<Element> with _LegacyFinderMixin {
  /// Creates a new [Finder] with the given `skipOffstage` value.
  Finder({this.skipOffstage = true});

  /// Whether this finder skips nodes that are offstage.
  ///
  /// If this is true, then the elements are walked using
  /// [Element.debugVisitOnstageChildren]. This skips offstage children of
  /// [Offstage] widgets, as well as children of inactive [Route]s.
  final bool skipOffstage;

  @override
  Finder get first => _FirstWidgetFinder(this);

  @override
  Finder get last => _LastWidgetFinder(this);

  @override
  Finder at(int index) => _IndexWidgetFinder(this, index);

  @override
  Iterable<Element> get allCandidates {
    return collectAllElementsFrom(WidgetsBinding.instance.rootElement!, skipOffstage: skipOffstage);
  }

  @override
  String describeMatch(Plurality plurality) {
    return switch (plurality) {
      Plurality.zero || Plurality.many => 'widgets with $description',
      Plurality.one => 'widget with $description',
    };
  }

  /// Returns a variant of this finder that only matches elements reachable by
  /// a hit test.
  ///
  /// The `at` parameter specifies the location relative to the size of the
  /// target element where the hit test is performed.
  Finder hitTestable({Alignment at = Alignment.center}) => _HitTestableWidgetFinder(this, at);
}

/// A base class for creating finders that search the semantics tree.
abstract class SemanticsFinder extends FinderBase<SemanticsNode> {
  /// Creates a new [SemanticsFinder] that will search within the given [view] or
  /// within all views if [view] is null.
  SemanticsFinder(this.view);

  /// The [FlutterView] whose semantics tree this finder will search.
  ///
  /// If null, the finder will search within all views.
  final FlutterView? view;

  /// Returns the root [SemanticsNode]s of all the semantics trees that this
  /// finder will search.
  Iterable<SemanticsNode> get roots {
    if (view == null) {
      return _allRoots;
    }
    final RenderView renderView = TestWidgetsFlutterBinding.instance.renderViews.firstWhere(
      (RenderView r) => r.flutterView == view,
    );
    return <SemanticsNode>[renderView.owner!.semanticsOwner!.rootSemanticsNode!];
  }

  @override
  Iterable<SemanticsNode> get allCandidates {
    return roots.expand((SemanticsNode root) => collectAllSemanticsNodesFrom(root));
  }

  static Iterable<SemanticsNode> get _allRoots {
    final roots = <SemanticsNode>[];
    void collectSemanticsRoots(PipelineOwner owner) {
      final SemanticsNode? root = owner.semanticsOwner?.rootSemanticsNode;
      if (root != null) {
        roots.add(root);
      }
      owner.visitChildren(collectSemanticsRoots);
    }

    collectSemanticsRoots(TestWidgetsFlutterBinding.instance.rootPipelineOwner);
    return roots;
  }
}

/// A base class for creating finders that search for static text rendered by a
/// [RenderParagraph].
class _StaticTextRangeFinder extends FinderBase<TextRangeContext> {
  /// Creates a new [_StaticTextRangeFinder] that searches for the given
  /// `pattern` in the [Element]s found by `_parent`.
  _StaticTextRangeFinder(this._parent, this.pattern);

  final FinderBase<Element> _parent;
  final Pattern pattern;

  Iterable<TextRangeContext> _flatMap(Element from) {
    final RenderObject? renderObject = from.renderObject;
    // This is currently only exposed on text matchers. Only consider RenderBoxes.
    if (renderObject is! RenderBox) {
      return const Iterable<TextRangeContext>.empty();
    }

    final View view = from.findAncestorWidgetOfExactType<View>()!;
    final paragraphs = <RenderParagraph>[];

    void visitor(RenderObject child) {
      switch (child) {
        case RenderParagraph():
          paragraphs.add(child);
        // No need to continue, we are piggybacking off of a text matcher, so
        // inline text widgets will be reported separately.
        case RenderBox():
          child.visitChildren(visitor);
        case _:
      }
    }

    visitor(renderObject);
    Iterable<TextRangeContext> searchInParagraph(RenderParagraph paragraph) {
      final String text = paragraph.text.toPlainText(includeSemanticsLabels: false);
      return pattern
          .allMatches(text)
          .map(
            (Match match) =>
                TextRangeContext._(view, paragraph, TextRange(start: match.start, end: match.end)),
          );
    }

    return paragraphs.expand(searchInParagraph);
  }

  @override
  Iterable<TextRangeContext> findInCandidates(Iterable<TextRangeContext> candidates) => candidates;

  @override
  Iterable<TextRangeContext> get allCandidates => _parent.evaluate().expand(_flatMap);

  @override
  String describeMatch(Plurality plurality) {
    return switch (plurality) {
      Plurality.zero ||
      Plurality.many => 'non-overlapping TextRanges that match the Pattern "$pattern"',
      Plurality.one => 'non-overlapping TextRange that matches the Pattern "$pattern"',
    };
  }
}

/// A mixin that applies additional filtering to the results of a parent [Finder].
mixin ChainedFinderMixin<CandidateType> on FinderBase<CandidateType> {
  /// Another finder whose results will be further filtered.
  FinderBase<CandidateType> get parent;

  /// Return another [Iterable] when given an [Iterable] of candidates from a
  /// parent [FinderBase].
  ///
  /// This is the main method to implement when mixing in [ChainedFinderMixin].
  Iterable<CandidateType> filter(Iterable<CandidateType> parentCandidates);

  @override
  Iterable<CandidateType> findInCandidates(Iterable<CandidateType> candidates) {
    return filter(parent.findInCandidates(candidates));
  }

  @override
  Iterable<CandidateType> get allCandidates => parent.allCandidates;
}

/// Applies additional filtering against a [parent] widget finder.
abstract class ChainedFinder extends Finder with ChainedFinderMixin<Element> {
  /// Create a Finder chained against the candidates of another `parent` [Finder].
  ChainedFinder(this.parent);

  @override
  final FinderBase<Element> parent;
}

mixin _FirstFinderMixin<CandidateType> on ChainedFinderMixin<CandidateType> {
  @override
  String describeMatch(Plurality plurality) {
    return '${parent.describeMatch(plurality)} (ignoring all but first)';
  }

  @override
  Iterable<CandidateType> filter(Iterable<CandidateType> parentCandidates) sync* {
    yield parentCandidates.first;
  }
}

class _FirstFinder<CandidateType> extends FinderBase<CandidateType>
    with ChainedFinderMixin<CandidateType>, _FirstFinderMixin<CandidateType> {
  _FirstFinder(this.parent);

  @override
  final FinderBase<CandidateType> parent;
}

class _FirstWidgetFinder extends ChainedFinder with _FirstFinderMixin<Element> {
  _FirstWidgetFinder(super.parent);

  @override
  String get description => describeMatch(Plurality.many);
}

mixin _LastFinderMixin<CandidateType> on ChainedFinderMixin<CandidateType> {
  @override
  String describeMatch(Plurality plurality) {
    return '${parent.describeMatch(plurality)} (ignoring all but last)';
  }

  @override
  Iterable<CandidateType> filter(Iterable<CandidateType> parentCandidates) sync* {
    yield parentCandidates.last;
  }
}

class _LastFinder<CandidateType> extends FinderBase<CandidateType>
    with ChainedFinderMixin<CandidateType>, _LastFinderMixin<CandidateType> {
  _LastFinder(this.parent);

  @override
  final FinderBase<CandidateType> parent;
}

class _LastWidgetFinder extends ChainedFinder with _LastFinderMixin<Element> {
  _LastWidgetFinder(super.parent);

  @override
  String get description => describeMatch(Plurality.many);
}

mixin _IndexFinderMixin<CandidateType> on ChainedFinderMixin<CandidateType> {
  int get index;

  @override
  String describeMatch(Plurality plurality) {
    return '${parent.describeMatch(plurality)} (ignoring all but index $index)';
  }

  @override
  Iterable<CandidateType> filter(Iterable<CandidateType> parentCandidates) sync* {
    yield parentCandidates.elementAt(index);
  }
}

class _IndexFinder<CandidateType> extends FinderBase<CandidateType>
    with ChainedFinderMixin<CandidateType>, _IndexFinderMixin<CandidateType> {
  _IndexFinder(this.parent, this.index);

  @override
  final int index;

  @override
  final FinderBase<CandidateType> parent;
}

class _IndexWidgetFinder extends ChainedFinder with _IndexFinderMixin<Element> {
  _IndexWidgetFinder(super.parent, this.index);

  @override
  final int index;

  @override
  String get description => describeMatch(Plurality.many);
}

class _HitTestableWidgetFinder extends ChainedFinder {
  _HitTestableWidgetFinder(super.parent, this.alignment);

  final Alignment alignment;

  @override
  String describeMatch(Plurality plurality) {
    return '${parent.describeMatch(plurality)} (considering only hit-testable widgets with a RenderBox)';
  }

  @override
  String get description => describeMatch(Plurality.many);

  @override
  Iterable<Element> filter(Iterable<Element> parentCandidates) sync* {
    for (final candidate in parentCandidates) {
      final int viewId = candidate.findAncestorWidgetOfExactType<View>()!.view.viewId;
      final RenderObject? object = candidate.renderObject;
      if (object is! RenderBox) {
        continue;
      }
      final Offset absoluteOffset = object.localToGlobal(alignment.alongSize(object.size));
      final hitResult = HitTestResult();
      WidgetsBinding.instance.hitTestInView(hitResult, absoluteOffset, viewId);
      final bool found = hitResult.path.any(
        (HitTestEntry entry) => isRenderObjectAncestorOfTarget(object, entry.target),
      );
      if (found) {
        yield candidate;
      }
    }
  }
}

/// A mixin for creating finders that search candidates for those that match
/// a given pattern.
mixin MatchFinderMixin<CandidateType> on FinderBase<CandidateType> {
  /// Returns true if the given element matches the pattern.
  ///
  /// When implementing a MatchFinder, this is the main method to override.
  bool matches(CandidateType candidate);

  @override
  Iterable<CandidateType> findInCandidates(Iterable<CandidateType> candidates) {
    return candidates.where(matches);
  }
}

/// Searches candidates for any that match a particular pattern.
abstract class MatchFinder extends Finder with MatchFinderMixin<Element> {
  /// Initializes a predicate-based Finder. Used by subclasses to initialize the
  /// `skipOffstage` property.
  MatchFinder({super.skipOffstage});
}

abstract class _MatchTextFinder extends MatchFinder {
  _MatchTextFinder({this.findRichText = false, super.skipOffstage});

  /// Whether standalone [RichText] widgets should be found or not.
  ///
  /// Defaults to `false`.
  ///
  /// If disabled, only [Text] widgets will be matched. [RichText] widgets
  /// *without* a [Text] ancestor will be ignored.
  /// If enabled, only [RichText] widgets will be matched. This *implicitly*
  /// matches [Text] widgets as well since they always insert a [RichText]
  /// child.
  ///
  /// In either case, [EditableText] widgets will also be matched.
  final bool findRichText;

  bool matchesText(String textToMatch);

  @override
  bool matches(Element candidate) {
    final Widget widget = candidate.widget;
    if (widget is EditableText) {
      return _matchesEditableText(widget);
    }

    if (!findRichText) {
      return _matchesNonRichText(widget);
    }
    // It would be sufficient to always use _matchesRichText if we wanted to
    // match both standalone RichText widgets as well as Text widgets. However,
    // the find.text() finder used to always ignore standalone RichText widgets,
    // which is why we need the _matchesNonRichText method in order to not be
    // backwards-compatible and not break existing tests.
    return _matchesRichText(widget);
  }

  bool _matchesRichText(Widget widget) {
    if (widget is RichText) {
      return matchesText(widget.text.toPlainText());
    }
    return false;
  }

  bool _matchesNonRichText(Widget widget) {
    if (widget is Text) {
      if (widget.data != null) {
        return matchesText(widget.data!);
      }
      assert(widget.textSpan != null);
      return matchesText(widget.textSpan!.toPlainText());
    }
    return false;
  }

  bool _matchesEditableText(EditableText widget) {
    return matchesText(widget.controller.text);
  }
}

class _TextWidgetFinder extends _MatchTextFinder {
  _TextWidgetFinder(this.text, {super.findRichText, super.skipOffstage});

  final String text;

  @override
  String get description => 'text "$text"';

  @override
  bool matchesText(String textToMatch) {
    return textToMatch == text;
  }
}

class _TextContainingWidgetFinder extends _MatchTextFinder {
  _TextContainingWidgetFinder(this.pattern, {super.findRichText, super.skipOffstage});

  final Pattern pattern;

  @override
  String get description => 'text containing $pattern';

  @override
  bool matchesText(String textToMatch) {
    return textToMatch.contains(pattern);
  }
}

class _KeyWidgetFinder extends MatchFinder {
  _KeyWidgetFinder(this.key, {super.skipOffstage});

  final Key key;

  @override
  String get description => 'key $key';

  @override
  bool matches(Element candidate) {
    return candidate.widget.key == key;
  }
}

class _SubtypeWidgetFinder<T extends Widget> extends MatchFinder {
  _SubtypeWidgetFinder({super.skipOffstage});

  @override
  String get description => 'is "$T"';

  @override
  bool matches(Element candidate) {
    return candidate.widget is T;
  }
}

class _TypeWidgetFinder extends MatchFinder {
  _TypeWidgetFinder(this.widgetType, {super.skipOffstage});

  final Type widgetType;

  @override
  String get description => 'type "$widgetType"';

  @override
  bool matches(Element candidate) {
    return candidate.widget.runtimeType == widgetType;
  }
}

class _ImageWidgetFinder extends MatchFinder {
  _ImageWidgetFinder(this.image, {super.skipOffstage});

  final ImageProvider image;

  @override
  String get description => 'image "$image"';

  @override
  bool matches(Element candidate) {
    final Widget widget = candidate.widget;
    if (widget is Image) {
      return widget.image == image;
    } else if (widget is FadeInImage) {
      return widget.image == image;
    }
    return false;
  }
}

class _IconWidgetFinder extends MatchFinder {
  _IconWidgetFinder(this.icon, {super.skipOffstage});

  final IconData icon;

  @override
  String get description => 'icon "$icon"';

  @override
  bool matches(Element candidate) {
    final Widget widget = candidate.widget;
    return widget is Icon && widget.icon == icon;
  }
}

class _ElementTypeWidgetFinder extends MatchFinder {
  _ElementTypeWidgetFinder(this.elementType, {super.skipOffstage});

  final Type elementType;

  @override
  String get description => 'type "$elementType"';

  @override
  bool matches(Element candidate) {
    return candidate.runtimeType == elementType;
  }
}

class _ExactWidgetFinder extends MatchFinder {
  _ExactWidgetFinder(this.widget, {super.skipOffstage});

  final Widget widget;

  @override
  String get description => 'the given widget ($widget)';

  @override
  bool matches(Element candidate) {
    return candidate.widget == widget;
  }
}

class _WidgetPredicateWidgetFinder extends MatchFinder {
  _WidgetPredicateWidgetFinder(this.predicate, {this._description, super.skipOffstage});

  final WidgetPredicate predicate;
  final String? _description;

  @override
  String get description => _description ?? 'widget matching predicate';

  @override
  bool matches(Element candidate) {
    return predicate(candidate.widget);
  }
}

class _ElementPredicateWidgetFinder extends MatchFinder {
  _ElementPredicateWidgetFinder(this.predicate, {this._description, super.skipOffstage});

  final ElementPredicate predicate;
  final String? _description;

  @override
  String get description => _description ?? 'element matching predicate';

  @override
  bool matches(Element candidate) {
    return predicate(candidate);
  }
}

class _PredicateSemanticsFinder extends SemanticsFinder with MatchFinderMixin<SemanticsNode> {
  _PredicateSemanticsFinder(this.predicate, DescribeMatchCallback? describeMatch, super.view)
    : _describeMatch = describeMatch;

  final SemanticsNodePredicate predicate;
  final DescribeMatchCallback? _describeMatch;

  @override
  String describeMatch(Plurality plurality) {
    return _describeMatch?.call(plurality) ?? 'matching semantics predicate';
  }

  @override
  bool matches(SemanticsNode candidate) {
    return predicate(candidate);
  }
}

mixin _DescendantFinderMixin<CandidateType> on FinderBase<CandidateType> {
  FinderBase<CandidateType> get ancestor;
  FinderBase<CandidateType> get descendant;
  bool get matchRoot;

  @override
  String describeMatch(Plurality plurality) {
    return '${descendant.describeMatch(plurality)} descending from '
        '${ancestor.describeMatch(plurality)}'
        '${matchRoot ? ' inclusive' : ''}';
  }

  @override
  Iterable<CandidateType> findInCandidates(Iterable<CandidateType> candidates) {
    final Iterable<CandidateType> descendants = descendant.evaluate();
    return candidates.where((CandidateType candidate) => descendants.contains(candidate));
  }

  @override
  Iterable<CandidateType> get allCandidates {
    final Iterable<CandidateType> ancestors = ancestor.evaluate();
    final List<CandidateType> candidates = ancestors
        .expand<CandidateType>((CandidateType ancestor) => _collectDescendants(ancestor))
        .toSet()
        .toList();
    if (matchRoot) {
      candidates.insertAll(0, ancestors);
    }
    return candidates;
  }

  Iterable<CandidateType> _collectDescendants(CandidateType root);
}

class _DescendantWidgetFinder extends Finder with _DescendantFinderMixin<Element> {
  _DescendantWidgetFinder(
    this.ancestor,
    this.descendant, {
    this.matchRoot = false,
    super.skipOffstage,
  });

  @override
  final FinderBase<Element> ancestor;
  @override
  final FinderBase<Element> descendant;
  @override
  final bool matchRoot;

  @override
  String get description => describeMatch(Plurality.many);

  @override
  Iterable<Element> _collectDescendants(Element root) {
    return collectAllElementsFrom(root, skipOffstage: skipOffstage);
  }
}

class _DescendantSemanticsFinder extends FinderBase<SemanticsNode>
    with _DescendantFinderMixin<SemanticsNode> {
  _DescendantSemanticsFinder(this.ancestor, this.descendant, {this.matchRoot = false});

  @override
  final FinderBase<SemanticsNode> ancestor;

  @override
  final FinderBase<SemanticsNode> descendant;

  @override
  final bool matchRoot;

  @override
  Iterable<SemanticsNode> _collectDescendants(SemanticsNode root) {
    return collectAllSemanticsNodesFrom(root);
  }
}

mixin _AncestorFinderMixin<CandidateType> on FinderBase<CandidateType> {
  FinderBase<CandidateType> get ancestor;
  FinderBase<CandidateType> get descendant;
  bool get matchLeaves;

  @override
  String describeMatch(Plurality plurality) {
    return '${ancestor.describeMatch(plurality)} that are ancestors of '
        '${descendant.describeMatch(plurality)}'
        '${matchLeaves ? ' inclusive' : ''}';
  }

  @override
  Iterable<CandidateType> findInCandidates(Iterable<CandidateType> candidates) {
    final Iterable<CandidateType> ancestors = ancestor.evaluate();
    return candidates.where((CandidateType element) => ancestors.contains(element));
  }

  @override
  Iterable<CandidateType> get allCandidates {
    final candidates = <CandidateType>[];
    for (final CandidateType leaf in descendant.evaluate()) {
      if (matchLeaves) {
        candidates.add(leaf);
      }
      candidates.addAll(_collectAncestors(leaf));
    }
    return candidates;
  }

  Iterable<CandidateType> _collectAncestors(CandidateType child);
}

class _AncestorWidgetFinder extends Finder with _AncestorFinderMixin<Element> {
  _AncestorWidgetFinder(this.descendant, this.ancestor, {this.matchLeaves = false})
    : super(skipOffstage: false);

  @override
  final FinderBase<Element> ancestor;
  @override
  final FinderBase<Element> descendant;
  @override
  final bool matchLeaves;

  @override
  String get description => describeMatch(Plurality.many);

  @override
  Iterable<Element> _collectAncestors(Element child) {
    final ancestors = <Element>[];
    child.visitAncestorElements((Element element) {
      ancestors.add(element);
      return true;
    });
    return ancestors;
  }
}

class _AncestorSemanticsFinder extends FinderBase<SemanticsNode>
    with _AncestorFinderMixin<SemanticsNode> {
  _AncestorSemanticsFinder(this.descendant, this.ancestor, this.matchLeaves);

  @override
  final FinderBase<SemanticsNode> ancestor;

  @override
  final FinderBase<SemanticsNode> descendant;

  @override
  final bool matchLeaves;

  @override
  Iterable<SemanticsNode> _collectAncestors(SemanticsNode child) {
    final ancestors = <SemanticsNode>[];
    while (child.parent != null) {
      ancestors.add(child.parent!);
      child = child.parent!;
    }
    return ancestors;
  }
}
