// 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 'framework.dart';

// Examples can assume:
// class MyWidget extends StatelessWidget { const MyWidget({super.key, required this.child}); final Widget child; @override Widget build(BuildContext context) => child; }

/// A lookup boundary controls what entities are visible to descendants of the
/// boundary via the static lookup methods provided by the boundary.
///
/// The static lookup methods of the boundary mirror the lookup methods by the
/// same name exposed on [BuildContext] and they can be used as direct
/// replacements. Unlike the methods on [BuildContext], these methods do not
/// find any ancestor entities of the closest [LookupBoundary] surrounding the
/// provided [BuildContext]. The root of the tree is an implicit lookup boundary.
///
/// {@tool snippet}
/// In the example below, the [LookupBoundary.findAncestorWidgetOfExactType]
/// call returns null because the [LookupBoundary] "hides" `MyWidget` from the
/// [BuildContext] that was queried.
///
/// ```dart
/// MyWidget(
///   child: LookupBoundary(
///     child: Builder(
///       builder: (BuildContext context) {
///         MyWidget? widget = LookupBoundary.findAncestorWidgetOfExactType<MyWidget>(context);
///         return Text('$widget'); // "null"
///       },
///     ),
///   ),
/// )
/// ```
/// {@end-tool}
///
/// A [LookupBoundary] only affects the behavior of the static lookup methods
/// defined on the boundary. It does not affect the behavior of the lookup
/// methods defined on [BuildContext].
///
/// A [LookupBoundary] is rarely instantiated directly. They are inserted at
/// locations of the widget tree where the render tree diverges from the element
/// tree, which is rather uncommon. Such anomalies are created by
/// [RenderObjectElement]s that don't attach their [RenderObject] to the closest
/// ancestor [RenderObjectElement], e.g. because they bootstrap a separate
/// stand-alone render tree.
// TODO(goderbauer): Reference the View widget here once available.
/// This behavior breaks the assumption some widgets have about the structure of
/// the render tree: These widgets may try to reach out to an ancestor widget,
/// assuming that their associated [RenderObject]s are also ancestors, which due
/// to the anomaly may not be the case. At the point where the divergence in the
/// two trees is introduced, a [LookupBoundary] can be used to hide that ancestor
/// from the querying widget.
///
/// As an example, [Material.of] relies on lookup boundaries to hide the
/// [Material] widget from certain descendant button widget. Buttons reach out
/// to their [Material] ancestor to draw ink splashes on its associated render
/// object. This only produces the desired effect if the button render object
/// is a descendant of the [Material] render object. If the element tree and
/// the render tree are not in sync due to anomalies described above, this may
/// not be the case. To avoid incorrect visuals, the [Material] relies on
/// lookup boundaries to hide itself from descendants in subtrees with such
/// anomalies. Those subtrees are expected to introduce their own [Material]
/// widget that buttons there can utilize without crossing a lookup boundary.
class LookupBoundary extends InheritedWidget {
  /// Creates a [LookupBoundary].
  ///
  /// A none-null [child] widget must be provided.
  const LookupBoundary({super.key, required super.child});

  /// Obtains the nearest widget of the given type `T` within the current
  /// [LookupBoundary] of `context`, which must be the type of a concrete
  /// [InheritedWidget] subclass, and registers the provided build `context`
  /// with that widget such that when that widget changes (or a new widget of
  /// that type is introduced, or the widget goes away), the build context is
  /// rebuilt so that it can obtain new values from that widget.
  ///
  /// This method behaves exactly like
  /// [BuildContext.dependOnInheritedWidgetOfExactType], except it only
  /// considers [InheritedWidget]s of the specified type `T` between the
  /// provided [BuildContext] and its closest [LookupBoundary] ancestor.
  /// [InheritedWidget]s past that [LookupBoundary] are invisible to this
  /// method. The root of the tree is treated as an implicit lookup boundary.
  ///
  /// {@macro flutter.widgets.BuildContext.dependOnInheritedWidgetOfExactType}
  static T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>(BuildContext context, { Object? aspect }) {
    // The following call makes sure that context depends on something so
    // Element.didChangeDependencies is called when context moves in the tree
    // even when requested dependency remains unfulfilled (i.e. null is
    // returned).
    context.dependOnInheritedWidgetOfExactType<LookupBoundary>();
    final InheritedElement? candidate = getElementForInheritedWidgetOfExactType<T>(context);
    if (candidate == null) {
      return null;
    }
    context.dependOnInheritedElement(candidate, aspect: aspect);
    return candidate.widget as T;
  }

  /// Obtains the element corresponding to the nearest widget of the given type
  /// `T` within the current [LookupBoundary] of `context`.
  ///
  /// `T` must be the type of a concrete [InheritedWidget] subclass. Returns
  /// null if no such element is found.
  ///
  /// This method behaves exactly like
  /// [BuildContext.getElementForInheritedWidgetOfExactType], except it only
  /// considers [InheritedWidget]s of the specified type `T` between the
  /// provided [BuildContext] and its closest [LookupBoundary] ancestor.
  /// [InheritedWidget]s past that [LookupBoundary] are invisible to this
  /// method. The root of the tree is treated as an implicit lookup boundary.
  ///
  /// {@macro flutter.widgets.BuildContext.getElementForInheritedWidgetOfExactType}
  static InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>(BuildContext context) {
    final InheritedElement? candidate = context.getElementForInheritedWidgetOfExactType<T>();
    if (candidate == null) {
      return null;
    }
    final Element? boundary = context.getElementForInheritedWidgetOfExactType<LookupBoundary>();
    if (boundary != null && boundary.depth > candidate.depth) {
      return null;
    }
    return candidate;
  }

  /// Returns the nearest ancestor widget of the given type `T` within the
  /// current [LookupBoundary] of `context`.
  ///
  /// `T` must be the type of a concrete [Widget] subclass.
  ///
  /// This method behaves exactly like
  /// [BuildContext.findAncestorWidgetOfExactType], except it only considers
  /// [Widget]s of the specified type `T` between the provided [BuildContext]
  /// and its closest [LookupBoundary] ancestor. [Widget]s past that
  /// [LookupBoundary] are invisible to this method. The root of the tree is
  /// treated as an implicit lookup boundary.
  ///
  /// {@macro flutter.widgets.BuildContext.findAncestorWidgetOfExactType}
  static T? findAncestorWidgetOfExactType<T extends Widget>(BuildContext context) {
    Element? target;
    context.visitAncestorElements((Element ancestor) {
      if (ancestor.widget.runtimeType == T) {
        target = ancestor;
        return false;
      }
      return ancestor.widget.runtimeType != LookupBoundary;
    });
    return target?.widget as T?;
  }

  /// Returns the [State] object of the nearest ancestor [StatefulWidget] widget
  /// within the current [LookupBoundary] of `context` that is an instance of
  /// the given type `T`.
  ///
  /// This method behaves exactly like
  /// [BuildContext.findAncestorWidgetOfExactType], except it only considers
  /// [State] objects of the specified type `T` between the provided
  /// [BuildContext] and its closest [LookupBoundary] ancestor. [State] objects
  /// past that [LookupBoundary] are invisible to this method. The root of the
  /// tree is treated as an implicit lookup boundary.
  ///
  /// {@macro flutter.widgets.BuildContext.findAncestorStateOfType}
  static T? findAncestorStateOfType<T extends State>(BuildContext context) {
    StatefulElement? target;
    context.visitAncestorElements((Element ancestor) {
      if (ancestor is StatefulElement && ancestor.state is T) {
        target = ancestor;
        return false;
      }
      return ancestor.widget.runtimeType != LookupBoundary;
    });
    return target?.state as T?;
  }

  /// Returns the [State] object of the furthest ancestor [StatefulWidget]
  /// widget within the current [LookupBoundary] of `context` that is an
  /// instance of the given type `T`.
  ///
  /// This method behaves exactly like
  /// [BuildContext.findRootAncestorStateOfType], except it considers the
  /// closest [LookupBoundary] ancestor of `context` to be the root. [State]
  /// objects past that [LookupBoundary] are invisible to this method. The root
  /// of the tree is treated as an implicit lookup boundary.
  ///
  /// {@macro flutter.widgets.BuildContext.findRootAncestorStateOfType}
  static T? findRootAncestorStateOfType<T extends State>(BuildContext context) {
    StatefulElement? target;
    context.visitAncestorElements((Element ancestor) {
      if (ancestor is StatefulElement && ancestor.state is T) {
        target = ancestor;
      }
      return ancestor.widget.runtimeType != LookupBoundary;
    });
    return target?.state as T?;
  }

  /// Returns the [RenderObject] object of the nearest ancestor
  /// [RenderObjectWidget] widget within the current [LookupBoundary] of
  /// `context` that is an instance of the given type `T`.
  ///
  /// This method behaves exactly like
  /// [BuildContext.findAncestorRenderObjectOfType], except it only considers
  /// [RenderObject]s of the specified type `T` between the provided
  /// [BuildContext] and its closest [LookupBoundary] ancestor. [RenderObject]s
  /// past that [LookupBoundary] are invisible to this method. The root of the
  /// tree is treated as an implicit lookup boundary.
  ///
  /// {@macro flutter.widgets.BuildContext.findAncestorRenderObjectOfType}
  static T? findAncestorRenderObjectOfType<T extends RenderObject>(BuildContext context) {
    Element? target;
    context.visitAncestorElements((Element ancestor) {
      if (ancestor is RenderObjectElement && ancestor.renderObject is T) {
        target = ancestor;
        return false;
      }
      return ancestor.widget.runtimeType != LookupBoundary;
    });
    return target?.renderObject as T?;
  }

  /// Walks the ancestor chain, starting with the parent of the build context's
  /// widget, invoking the argument for each ancestor until a [LookupBoundary]
  /// or the root is reached.
  ///
  /// This method behaves exactly like [BuildContext.visitAncestorElements],
  /// except it only walks the tree up to the closest [LookupBoundary] ancestor
  /// of the provided context. The root of the tree is treated as an implicit
  /// lookup boundary.
  ///
  /// {@macro flutter.widgets.BuildContext.visitAncestorElements}
  static void visitAncestorElements(BuildContext context, ConditionalElementVisitor visitor) {
    context.visitAncestorElements((Element ancestor) {
      return visitor(ancestor) && ancestor.widget.runtimeType != LookupBoundary;
    });
  }

  /// Walks the non-[LookupBoundary] child [Element]s of the provided
  /// `context`.
  ///
  /// This method behaves exactly like [BuildContext.visitChildElements],
  /// except it only visits children that are not a [LookupBoundary].
  ///
  /// {@macro flutter.widgets.BuildContext.visitChildElements}
  static void visitChildElements(BuildContext context, ElementVisitor visitor) {
    context.visitChildElements((Element child) {
      if (child.widget.runtimeType != LookupBoundary) {
        visitor(child);
      }
    });
  }

  /// Returns true if a [LookupBoundary] is hiding the nearest
  /// [Widget] of the specified type `T` from the provided [BuildContext].
  ///
  /// This method throws when asserts are disabled.
  static bool debugIsHidingAncestorWidgetOfExactType<T extends Widget>(BuildContext context) {
    bool? result;
    assert(() {
      bool hiddenByBoundary = false;
      bool ancestorFound = false;
      context.visitAncestorElements((Element ancestor) {
        if (ancestor.widget.runtimeType == T) {
          ancestorFound = true;
          return false;
        }
        hiddenByBoundary = hiddenByBoundary || ancestor.widget.runtimeType == LookupBoundary;
        return true;
      });
      result = ancestorFound & hiddenByBoundary;
      return true;
    } ());
    return result!;
  }

  /// Returns true if a [LookupBoundary] is hiding the nearest [StatefulWidget]
  /// with a [State] of the specified type `T` from the provided [BuildContext].
  ///
  /// This method throws when asserts are disabled.
  static bool debugIsHidingAncestorStateOfType<T extends State>(BuildContext context) {
    bool? result;
    assert(() {
      bool hiddenByBoundary = false;
      bool ancestorFound = false;
      context.visitAncestorElements((Element ancestor) {
        if (ancestor is StatefulElement && ancestor.state is T) {
          ancestorFound = true;
          return false;
        }
        hiddenByBoundary = hiddenByBoundary || ancestor.widget.runtimeType == LookupBoundary;
        return true;
      });
      result = ancestorFound & hiddenByBoundary;
      return true;
    } ());
    return result!;
  }

  /// Returns true if a [LookupBoundary] is hiding the nearest
  /// [RenderObjectWidget] with a [RenderObject] of the specified type `T`
  /// from the provided [BuildContext].
  ///
  /// This method throws when asserts are disabled.
  static bool debugIsHidingAncestorRenderObjectOfType<T extends RenderObject>(BuildContext context) {
    bool? result;
    assert(() {
      bool hiddenByBoundary = false;
      bool ancestorFound = false;
      context.visitAncestorElements((Element ancestor) {
        if (ancestor is RenderObjectElement && ancestor.renderObject is T) {
          ancestorFound = true;
          return false;
        }
        hiddenByBoundary = hiddenByBoundary || ancestor.widget.runtimeType == LookupBoundary;
        return true;
      });
      result = ancestorFound & hiddenByBoundary;
      return true;
    } ());
    return result!;
  }

  @override
  bool updateShouldNotify(covariant InheritedWidget oldWidget) => false;
}
