// 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 'package:flutter/foundation.dart';

import 'basic.dart';
import 'focus_manager.dart';
import 'framework.dart';
import 'inherited_notifier.dart';

/// A widget that manages a [FocusNode] to allow keyboard focus to be given
/// to this widget and its descendants.
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=JCDfh5bs1xc}
///
/// When the focus is gained or lost, [onFocusChange] is called.
///
/// For keyboard events, [onKey] and [onKeyEvent] are called if
/// [FocusNode.hasFocus] is true for this widget's [focusNode], unless a focused
/// descendant's [onKey] or [onKeyEvent] callback returned
/// [KeyEventResult.handled] when called.
///
/// This widget does not provide any visual indication that the focus has
/// changed. Any desired visual changes should be made when [onFocusChange] is
/// called.
///
/// To access the [FocusNode] of the nearest ancestor [Focus] widget and
/// establish a relationship that will rebuild the widget when the focus
/// changes, use the [Focus.of] and [FocusScope.of] static methods.
///
/// To access the focused state of the nearest [Focus] widget, use
/// [FocusNode.hasFocus] from a build method, which also establishes a
/// relationship between the calling widget and the [Focus] widget that will
/// rebuild the calling widget when the focus changes.
///
/// Managing a [FocusNode] means managing its lifecycle, listening for changes
/// in focus, and re-parenting it when needed to keep the focus hierarchy in
/// sync with the widget hierarchy. This widget does all of those things for
/// you. See [FocusNode] for more information about the details of what node
/// management entails if you are not using a [Focus] widget and you need to do
/// it yourself.
///
/// If the [Focus] default constructor is used, then this widget will manage any
/// given [focusNode] by overwriting the appropriate values of the [focusNode]
/// with the values of [FocusNode.onKey], [FocusNode.onKeyEvent],
/// [FocusNode.skipTraversal], [FocusNode.canRequestFocus], and
/// [FocusNode.descendantsAreFocusable] whenever the [Focus] widget is updated.
///
/// If the [Focus.withExternalFocusNode] is used instead, then the values
/// returned by [onKey], [onKeyEvent], [skipTraversal], [canRequestFocus], and
/// [descendantsAreFocusable] will be the values in the external focus node, and
/// the external focus node's values will not be overwritten when the widget is
/// updated.
///
/// To collect a sub-tree of nodes into an exclusive group that restricts focus
/// traversal to the group, use a [FocusScope]. To collect a sub-tree of nodes
/// into a group that has a specific order to its traversal but allows the
/// traversal to escape the group, use a [FocusTraversalGroup].
///
/// To move the focus, use methods on [FocusNode] by getting the [FocusNode]
/// through the [of] method. For instance, to move the focus to the next node in
/// the focus traversal order, call `Focus.of(context).nextFocus()`. To unfocus
/// a widget, call `Focus.of(context).unfocus()`.
///
/// {@tool dartpad}
/// This example shows how to manage focus using the [Focus] and [FocusScope]
/// widgets. See [FocusNode] for a similar example that doesn't use [Focus] or
/// [FocusScope].
///
/// ** See code in examples/api/lib/widgets/focus_scope/focus.0.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This example shows how to wrap another widget in a [Focus] widget to make it
/// focusable. It wraps a [Container], and changes the container's color when it
/// is set as the [FocusManager.primaryFocus].
///
/// If you also want to handle mouse hover and/or keyboard actions on a widget,
/// consider using a [FocusableActionDetector], which combines several different
/// widgets to provide those capabilities.
///
/// ** See code in examples/api/lib/widgets/focus_scope/focus.1.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This example shows how to focus a newly-created widget immediately after it
/// is created.
///
/// The focus node will not actually be given the focus until after the frame in
/// which it has requested focus is drawn, so it is OK to call
/// [FocusNode.requestFocus] on a node which is not yet in the focus tree.
///
/// ** See code in examples/api/lib/widgets/focus_scope/focus.2.dart **
/// {@end-tool}
///
/// See also:
///
///  * [FocusNode], which represents a node in the focus hierarchy and
///    [FocusNode]'s API documentation includes a detailed explanation of its role
///    in the overall focus system.
///  * [FocusScope], a widget that manages a group of focusable widgets using a
///    [FocusScopeNode].
///  * [FocusScopeNode], a node that collects focus nodes into a group for
///    traversal.
///  * [FocusManager], a singleton that manages the primary focus and
///    distributes key events to focused nodes.
///  * [FocusTraversalPolicy], an object used to determine how to move the focus
///    to other nodes.
///  * [FocusTraversalGroup], a widget that groups together and imposes a
///    traversal policy on the [Focus] nodes below it in the widget hierarchy.
class Focus extends StatefulWidget {
  /// Creates a widget that manages a [FocusNode].
  ///
  /// The [child] argument is required and must not be null.
  ///
  /// The [autofocus] argument must not be null.
  const Focus({
    super.key,
    required this.child,
    this.focusNode,
    this.parentNode,
    this.autofocus = false,
    this.onFocusChange,
    FocusOnKeyEventCallback? onKeyEvent,
    FocusOnKeyCallback? onKey,
    bool? canRequestFocus,
    bool? skipTraversal,
    bool? descendantsAreFocusable,
    bool? descendantsAreTraversable,
    this.includeSemantics = true,
    String? debugLabel,
  })  : _onKeyEvent = onKeyEvent,
        _onKey = onKey,
        _canRequestFocus = canRequestFocus,
        _skipTraversal = skipTraversal,
        _descendantsAreFocusable = descendantsAreFocusable,
        _descendantsAreTraversable = descendantsAreTraversable,
        _debugLabel = debugLabel;

  /// Creates a Focus widget that uses the given [focusNode] as the source of
  /// truth for attributes on the node, rather than the attributes of this widget.
  const factory Focus.withExternalFocusNode({
    Key? key,
    required Widget child,
    required FocusNode focusNode,
    FocusNode? parentNode,
    bool autofocus,
    ValueChanged<bool>? onFocusChange,
    bool includeSemantics,
  }) = _FocusWithExternalFocusNode;

  // Indicates whether the widget's focusNode attributes should have priority
  // when then widget is updated.
  bool get _usingExternalFocus => false;

  /// The optional parent node to use when reparenting the [focusNode] for this
  /// [Focus] widget.
  ///
  /// If [parentNode] is null, then [Focus.maybeOf] is used to find the parent
  /// in the widget tree, which is typically what is desired, since it is easier
  /// to reason about the focus tree if it mirrors the shape of the widget tree.
  ///
  /// Set this property if the focus tree needs to have a different shape than
  /// the widget tree. This is typically in cases where a dialog is in an
  /// [Overlay] (or another part of the widget tree), and focus should
  /// behave as if the widgets in the overlay are descendants of the given
  /// [parentNode] for purposes of focus.
  ///
  /// Defaults to null.
  final FocusNode? parentNode;

  /// The child widget of this [Focus].
  ///
  /// {@macro flutter.widgets.ProxyWidget.child}
  final Widget child;

  /// {@template flutter.widgets.Focus.focusNode}
  /// An optional focus node to use as the focus node for this widget.
  ///
  /// If one is not supplied, then one will be automatically allocated, owned,
  /// and managed by this widget. The widget will be focusable even if a
  /// [focusNode] is not supplied. If supplied, the given [focusNode] will be
  /// _hosted_ by this widget, but not owned. See [FocusNode] for more
  /// information on what being hosted and/or owned implies.
  ///
  /// Supplying a focus node is sometimes useful if an ancestor to this widget
  /// wants to control when this widget has the focus. The owner will be
  /// responsible for calling [FocusNode.dispose] on the focus node when it is
  /// done with it, but this widget will attach/detach and reparent the node
  /// when needed.
  /// {@endtemplate}
  ///
  /// A non-null [focusNode] must be supplied if using the
  /// [Focus.withExternalFocusNode] constructor.
  final FocusNode? focusNode;

  /// {@template flutter.widgets.Focus.autofocus}
  /// True if this widget will be selected as the initial focus when no other
  /// node in its scope is currently focused.
  ///
  /// Ideally, there is only one widget with autofocus set in each [FocusScope].
  /// If there is more than one widget with autofocus set, then the first one
  /// added to the tree will get focus.
  ///
  /// Must not be null. Defaults to false.
  /// {@endtemplate}
  final bool autofocus;

  /// Handler called when the focus changes.
  ///
  /// Called with true if this widget's node gains focus, and false if it loses
  /// focus.
  final ValueChanged<bool>? onFocusChange;

  /// A handler for keys that are pressed when this object or one of its
  /// children has focus.
  ///
  /// Key events are first given to the [FocusNode] that has primary focus, and
  /// if its [onKeyEvent] method returns [KeyEventResult.ignored], then they are
  /// given to each ancestor node up the focus hierarchy in turn. If an event
  /// reaches the root of the hierarchy, it is discarded.
  ///
  /// This is not the way to get text input in the manner of a text field: it
  /// leaves out support for input method editors, and doesn't support soft
  /// keyboards in general. For text input, consider [TextField],
  /// [EditableText], or [CupertinoTextField] instead, which do support these
  /// things.
  FocusOnKeyEventCallback? get onKeyEvent => _onKeyEvent ?? focusNode?.onKeyEvent;
  final FocusOnKeyEventCallback? _onKeyEvent;

  /// A handler for keys that are pressed when this object or one of its
  /// children has focus.
  ///
  /// This is a legacy API based on [RawKeyEvent] and will be deprecated in the
  /// future. Prefer [onKeyEvent] instead.
  ///
  /// Key events are first given to the [FocusNode] that has primary focus, and
  /// if its [onKey] method return false, then they are given to each ancestor
  /// node up the focus hierarchy in turn. If an event reaches the root of the
  /// hierarchy, it is discarded.
  ///
  /// This is not the way to get text input in the manner of a text field: it
  /// leaves out support for input method editors, and doesn't support soft
  /// keyboards in general. For text input, consider [TextField],
  /// [EditableText], or [CupertinoTextField] instead, which do support these
  /// things.
  FocusOnKeyCallback? get onKey => _onKey ?? focusNode?.onKey;
  final FocusOnKeyCallback? _onKey;

  /// {@template flutter.widgets.Focus.canRequestFocus}
  /// If true, this widget may request the primary focus.
  ///
  /// Defaults to true. Set to false if you want the [FocusNode] this widget
  /// manages to do nothing when [FocusNode.requestFocus] is called on it. Does
  /// not affect the children of this node, and [FocusNode.hasFocus] can still
  /// return true if this node is the ancestor of the primary focus.
  ///
  /// This is different than [Focus.skipTraversal] because [Focus.skipTraversal]
  /// still allows the widget to be focused, just not traversed to.
  ///
  /// Setting [FocusNode.canRequestFocus] to false implies that the widget will
  /// also be skipped for traversal purposes.
  ///
  /// See also:
  ///
  /// * [FocusTraversalGroup], a widget that sets the traversal policy for its
  ///   descendants.
  /// * [FocusTraversalPolicy], a class that can be extended to describe a
  ///   traversal policy.
  /// {@endtemplate}
  bool get canRequestFocus => _canRequestFocus ?? focusNode?.canRequestFocus ?? true;
  final bool? _canRequestFocus;

  /// Sets the [FocusNode.skipTraversal] flag on the focus node so that it won't
  /// be visited by the [FocusTraversalPolicy].
  ///
  /// This is sometimes useful if a [Focus] widget should receive key events as
  /// part of the focus chain, but shouldn't be accessible via focus traversal.
  ///
  /// This is different from [FocusNode.canRequestFocus] because it only implies
  /// that the widget can't be reached via traversal, not that it can't be
  /// focused. It may still be focused explicitly.
  bool get skipTraversal => _skipTraversal ?? focusNode?.skipTraversal ?? false;
  final bool? _skipTraversal;

  /// {@template flutter.widgets.Focus.descendantsAreFocusable}
  /// If false, will make this widget's descendants unfocusable.
  ///
  /// Defaults to true. Does not affect focusability of this node (just its
  /// descendants): for that, use [FocusNode.canRequestFocus].
  ///
  /// If any descendants are focused when this is set to false, they will be
  /// unfocused. When [descendantsAreFocusable] is set to true again, they will
  /// not be refocused, although they will be able to accept focus again.
  ///
  /// Does not affect the value of [FocusNode.canRequestFocus] on the
  /// descendants.
  ///
  /// If a descendant node loses focus when this value is changed, the focus
  /// will move to the scope enclosing this node.
  ///
  /// See also:
  ///
  /// * [ExcludeFocus], a widget that uses this property to conditionally
  ///   exclude focus for a subtree.
  /// * [descendantsAreTraversable], which makes this widget's descendants
  ///   untraversable.
  /// * [ExcludeFocusTraversal], a widget that conditionally excludes focus
  ///   traversal for a subtree.
  /// * [FocusTraversalGroup], a widget used to group together and configure the
  ///   focus traversal policy for a widget subtree that has a
  ///   `descendantsAreFocusable` parameter to conditionally block focus for a
  ///   subtree.
  /// {@endtemplate}
  bool get descendantsAreFocusable => _descendantsAreFocusable ?? focusNode?.descendantsAreFocusable ?? true;
  final bool? _descendantsAreFocusable;

  /// {@template flutter.widgets.Focus.descendantsAreTraversable}
  /// If false, will make this widget's descendants untraversable.
  ///
  /// Defaults to true. Does not affect traversablility of this node (just its
  /// descendants): for that, use [FocusNode.skipTraversal].
  ///
  /// Does not affect the value of [FocusNode.skipTraversal] on the
  /// descendants. Does not affect focusability of the descendants.
  ///
  /// See also:
  ///
  /// * [ExcludeFocusTraversal], a widget that uses this property to
  ///   conditionally exclude focus traversal for a subtree.
  /// * [descendantsAreFocusable], which makes this widget's descendants
  ///   unfocusable.
  /// * [ExcludeFocus], a widget that conditionally excludes focus for a subtree.
  /// * [FocusTraversalGroup], a widget used to group together and configure the
  ///   focus traversal policy for a widget subtree that has a
  ///   `descendantsAreFocusable` parameter to conditionally block focus for a
  ///   subtree.
  /// {@endtemplate}
  bool get descendantsAreTraversable => _descendantsAreTraversable ?? focusNode?.descendantsAreTraversable ?? true;
  final bool? _descendantsAreTraversable;

  /// {@template flutter.widgets.Focus.includeSemantics}
  /// Include semantics information in this widget.
  ///
  /// If true, this widget will include a [Semantics] node that indicates the
  /// [SemanticsProperties.focusable] and [SemanticsProperties.focused]
  /// properties.
  ///
  /// It is not typical to set this to false, as that can affect the semantics
  /// information available to accessibility systems.
  ///
  /// Must not be null, defaults to true.
  /// {@endtemplate}
  final bool includeSemantics;

  /// A debug label for this widget.
  ///
  /// Not used for anything except to be printed in the diagnostic output from
  /// [toString] or [toStringDeep].
  ///
  /// To get a string with the entire tree, call [debugDescribeFocusTree]. To
  /// print it to the console call [debugDumpFocusTree].
  ///
  /// Defaults to null.
  String? get debugLabel => _debugLabel ?? focusNode?.debugLabel;
  final String? _debugLabel;

  /// Returns the [focusNode] of the [Focus] that most tightly encloses the
  /// given [BuildContext].
  ///
  /// If no [Focus] node is found before reaching the nearest [FocusScope]
  /// widget, or there is no [Focus] widget in scope, then this method will
  /// throw an exception.
  ///
  /// The `context` and `scopeOk` arguments must not be null.
  ///
  /// Calling this function creates a dependency that will rebuild the given
  /// context when the focus changes.
  ///
  /// See also:
  ///
  ///  * [maybeOf], which is similar to this function, but will return null
  ///    instead of throwing if it doesn't find a [Focus] node.
  static FocusNode of(BuildContext context, { bool scopeOk = false }) {
    final _FocusInheritedScope? marker = context.dependOnInheritedWidgetOfExactType<_FocusInheritedScope>();
    final FocusNode? node = marker?.notifier;
    assert(() {
      if (node == null) {
        throw FlutterError(
          'Focus.of() was called with a context that does not contain a Focus widget.\n'
          'No Focus widget ancestor could be found starting from the context that was passed to '
          'Focus.of(). This can happen because you are using a widget that looks for a Focus '
          'ancestor, and do not have a Focus widget descendant in the nearest FocusScope.\n'
          'The context used was:\n'
          '  $context',
        );
      }
      return true;
    }());
    assert(() {
      if (!scopeOk && node is FocusScopeNode) {
        throw FlutterError(
          'Focus.of() was called with a context that does not contain a Focus between the given '
          'context and the nearest FocusScope widget.\n'
          'No Focus ancestor could be found starting from the context that was passed to '
          'Focus.of() to the point where it found the nearest FocusScope widget. This can happen '
          'because you are using a widget that looks for a Focus ancestor, and do not have a '
          'Focus widget ancestor in the current FocusScope.\n'
          'The context used was:\n'
          '  $context',
        );
      }
      return true;
    }());
    return node!;
  }

  /// Returns the [focusNode] of the [Focus] that most tightly encloses the
  /// given [BuildContext].
  ///
  /// If no [Focus] node is found before reaching the nearest [FocusScope]
  /// widget, or there is no [Focus] widget in scope, then this method will
  /// return null.
  ///
  /// The `context` and `scopeOk` arguments must not be null.
  ///
  /// Calling this function creates a dependency that will rebuild the given
  /// context when the focus changes.
  ///
  /// See also:
  ///
  ///  * [of], which is similar to this function, but will throw an exception if
  ///    it doesn't find a [Focus] node instead of returning null.
  static FocusNode? maybeOf(BuildContext context, { bool scopeOk = false }) {
    final _FocusInheritedScope? marker = context.dependOnInheritedWidgetOfExactType<_FocusInheritedScope>();
    final FocusNode? node = marker?.notifier;
    if (node == null) {
      return null;
    }
    if (!scopeOk && node is FocusScopeNode) {
      return null;
    }
    return node;
  }

  /// Returns true if the nearest enclosing [Focus] widget's node is focused.
  ///
  /// A convenience method to allow build methods to write:
  /// `Focus.isAt(context)` to get whether or not the nearest [Focus] above them
  /// in the widget hierarchy currently has the input focus.
  ///
  /// Returns false if no [Focus] widget is found before reaching the nearest
  /// [FocusScope], or if the root of the focus tree is reached without finding
  /// a [Focus] widget.
  ///
  /// Calling this function creates a dependency that will rebuild the given
  /// context when the focus changes.
  static bool isAt(BuildContext context) => Focus.maybeOf(context)?.hasFocus ?? false;

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('debugLabel', debugLabel, defaultValue: null));
    properties.add(FlagProperty('autofocus', value: autofocus, ifTrue: 'AUTOFOCUS', defaultValue: false));
    properties.add(FlagProperty('canRequestFocus', value: canRequestFocus, ifFalse: 'NOT FOCUSABLE', defaultValue: false));
    properties.add(FlagProperty('descendantsAreFocusable', value: descendantsAreFocusable, ifFalse: 'DESCENDANTS UNFOCUSABLE', defaultValue: true));
    properties.add(FlagProperty('descendantsAreTraversable', value: descendantsAreTraversable, ifFalse: 'DESCENDANTS UNTRAVERSABLE', defaultValue: true));
    properties.add(DiagnosticsProperty<FocusNode>('focusNode', focusNode, defaultValue: null));
  }

  @override
  State<Focus> createState() => _FocusState();
}

// Implements the behavior differences when the Focus.withExternalFocusNode
// constructor is used.
class _FocusWithExternalFocusNode extends Focus {
  const _FocusWithExternalFocusNode({
    super.key,
    required super.child,
    required FocusNode super.focusNode,
    super.parentNode,
    super.autofocus,
    super.onFocusChange,
    super.includeSemantics,
  });

  @override
  bool get _usingExternalFocus => true;
  @override
  FocusOnKeyEventCallback? get onKeyEvent => focusNode!.onKeyEvent;
  @override
  FocusOnKeyCallback? get onKey => focusNode!.onKey;
  @override
  bool get canRequestFocus => focusNode!.canRequestFocus;
  @override
  bool get skipTraversal => focusNode!.skipTraversal;
  @override
  bool get descendantsAreFocusable => focusNode!.descendantsAreFocusable;
  @override
  bool? get _descendantsAreTraversable => focusNode!.descendantsAreTraversable;
  @override
  String? get debugLabel => focusNode!.debugLabel;
}

class _FocusState extends State<Focus> {
  FocusNode? _internalNode;
  FocusNode get focusNode => widget.focusNode ?? _internalNode!;
  late bool _hadPrimaryFocus;
  late bool _couldRequestFocus;
  late bool _descendantsWereFocusable;
  late bool _descendantsWereTraversable;
  bool _didAutofocus = false;
  FocusAttachment? _focusAttachment;

  @override
  void initState() {
    super.initState();
    _initNode();
  }

  void _initNode() {
    if (widget.focusNode == null) {
      // Only create a new node if the widget doesn't have one.
      // This calls a function instead of just allocating in place because
      // _createNode is overridden in _FocusScopeState.
      _internalNode ??= _createNode();
    }
    focusNode.descendantsAreFocusable = widget.descendantsAreFocusable;
    focusNode.descendantsAreTraversable = widget.descendantsAreTraversable;
    focusNode.skipTraversal = widget.skipTraversal;
    if (widget._canRequestFocus != null) {
      focusNode.canRequestFocus = widget._canRequestFocus!;
    }
    _couldRequestFocus = focusNode.canRequestFocus;
    _descendantsWereFocusable = focusNode.descendantsAreFocusable;
    _descendantsWereTraversable = focusNode.descendantsAreTraversable;
    _hadPrimaryFocus = focusNode.hasPrimaryFocus;
    _focusAttachment = focusNode.attach(context, onKeyEvent: widget.onKeyEvent, onKey: widget.onKey);

    // Add listener even if the _internalNode existed before, since it should
    // not be listening now if we're re-using a previous one because it should
    // have already removed its listener.
    focusNode.addListener(_handleFocusChanged);
  }

  FocusNode _createNode() {
    return FocusNode(
      debugLabel: widget.debugLabel,
      canRequestFocus: widget.canRequestFocus,
      descendantsAreFocusable: widget.descendantsAreFocusable,
      descendantsAreTraversable: widget.descendantsAreTraversable,
      skipTraversal: widget.skipTraversal,
    );
  }

  @override
  void dispose() {
    // Regardless of the node owner, we need to remove it from the tree and stop
    // listening to it.
    focusNode.removeListener(_handleFocusChanged);
    _focusAttachment!.detach();

    // Don't manage the lifetime of external nodes given to the widget, just the
    // internal node.
    _internalNode?.dispose();
    super.dispose();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _focusAttachment?.reparent();
    _handleAutofocus();
  }

  void _handleAutofocus() {
    if (!_didAutofocus && widget.autofocus) {
      FocusScope.of(context).autofocus(focusNode);
      _didAutofocus = true;
    }
  }

  @override
  void deactivate() {
    super.deactivate();
    // The focus node's location in the tree is no longer valid here. But
    // we can't unfocus or remove the node from the tree because if the widget
    // is moved to a different part of the tree (via global key) it should
    // retain its focus state. That's why we temporarily park it on the root
    // focus node (via reparent) until it either gets moved to a different part
    // of the tree (via didChangeDependencies) or until it is disposed.
    _focusAttachment?.reparent();
    _didAutofocus = false;
  }

  @override
  void didUpdateWidget(Focus oldWidget) {
    super.didUpdateWidget(oldWidget);
    assert(() {
      // Only update the debug label in debug builds.
      if (oldWidget.focusNode == widget.focusNode &&
          !widget._usingExternalFocus &&
          oldWidget.debugLabel != widget.debugLabel) {
        focusNode.debugLabel = widget.debugLabel;
      }
      return true;
    }());

    if (oldWidget.focusNode == widget.focusNode) {
      if (!widget._usingExternalFocus) {
        if (widget.onKey != focusNode.onKey) {
          focusNode.onKey = widget.onKey;
        }
        if (widget.onKeyEvent != focusNode.onKeyEvent) {
          focusNode.onKeyEvent = widget.onKeyEvent;
        }
        focusNode.skipTraversal = widget.skipTraversal;
        if (widget._canRequestFocus != null) {
          focusNode.canRequestFocus = widget._canRequestFocus!;
        }
        focusNode.descendantsAreFocusable = widget.descendantsAreFocusable;
        focusNode.descendantsAreTraversable = widget.descendantsAreTraversable;
      }
    } else {
      _focusAttachment!.detach();
      oldWidget.focusNode?.removeListener(_handleFocusChanged);
      _initNode();
    }

    if (oldWidget.autofocus != widget.autofocus) {
      _handleAutofocus();
    }
  }

  void _handleFocusChanged() {
    final bool hasPrimaryFocus = focusNode.hasPrimaryFocus;
    final bool canRequestFocus = focusNode.canRequestFocus;
    final bool descendantsAreFocusable = focusNode.descendantsAreFocusable;
    final bool descendantsAreTraversable = focusNode.descendantsAreTraversable;
    widget.onFocusChange?.call(focusNode.hasFocus);
    // Check the cached states that matter here, and call setState if they have
    // changed.
    if (_hadPrimaryFocus != hasPrimaryFocus) {
      setState(() {
        _hadPrimaryFocus = hasPrimaryFocus;
      });
    }
    if (_couldRequestFocus != canRequestFocus) {
      setState(() {
        _couldRequestFocus = canRequestFocus;
      });
    }
    if (_descendantsWereFocusable != descendantsAreFocusable) {
      setState(() {
        _descendantsWereFocusable = descendantsAreFocusable;
      });
    }
    if (_descendantsWereTraversable != descendantsAreTraversable) {
      setState(() {
        _descendantsWereTraversable = descendantsAreTraversable;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    _focusAttachment!.reparent(parent: widget.parentNode);
    Widget child = widget.child;
    if (widget.includeSemantics) {
      child = Semantics(
        focusable: _couldRequestFocus,
        focused: _hadPrimaryFocus,
        child: widget.child,
      );
    }
    return _FocusInheritedScope(
      node: focusNode,
      child: child,
    );
  }
}

/// A [FocusScope] is similar to a [Focus], but also serves as a scope for its
/// descendants, restricting focus traversal to the scoped controls.
///
/// For example a new [FocusScope] is created automatically when a route is
/// pushed, keeping the focus traversal from moving to a control in a previous
/// route.
///
/// If you just want to group widgets together in a group so that they are
/// traversed in a particular order, but the focus can still leave the group,
/// use a [FocusTraversalGroup].
///
/// Like [Focus], [FocusScope] provides an [onFocusChange] as a way to be
/// notified when the focus is given to or removed from this widget.
///
/// The [onKey] argument allows specification of a key event handler that is
/// invoked when this node or one of its children has focus. Keys are handed to
/// the primary focused widget first, and then they propagate through the
/// ancestors of that node, stopping if one of them returns
/// [KeyEventResult.handled] from [onKey], indicating that it has handled the
/// event.
///
/// Managing a [FocusScopeNode] means managing its lifecycle, listening for
/// changes in focus, and re-parenting it when needed to keep the focus
/// hierarchy in sync with the widget hierarchy. This widget does all of those
/// things for you. See [FocusScopeNode] for more information about the details
/// of what node management entails if you are not using a [FocusScope] widget
/// and you need to do it yourself.
///
/// [FocusScopeNode]s remember the last [FocusNode] that was focused within
/// their descendants, and can move that focus to the next/previous node, or a
/// node in a particular direction when the [FocusNode.nextFocus],
/// [FocusNode.previousFocus], or [FocusNode.focusInDirection] are called on a
/// [FocusNode] or [FocusScopeNode].
///
/// To move the focus, use methods on [FocusNode] by getting the [FocusNode]
/// through the [of] method. For instance, to move the focus to the next node in
/// the focus traversal order, call `Focus.of(context).nextFocus()`. To unfocus
/// a widget, call `Focus.of(context).unfocus()`.
///
/// {@tool dartpad}
/// This example demonstrates using a [FocusScope] to restrict focus to a particular
/// portion of the app. In this case, restricting focus to the visible part of a
/// Stack.
///
/// ** See code in examples/api/lib/widgets/focus_scope/focus_scope.0.dart **
/// {@end-tool}
///
/// See also:
///
///  * [FocusScopeNode], which represents a scope node in the focus hierarchy.
///  * [FocusNode], which represents a node in the focus hierarchy and has an
///    explanation of the focus system.
///  * [Focus], a widget that manages a [FocusNode] and allows easy access to
///    managing focus without having to manage the node.
///  * [FocusManager], a singleton that manages the focus and distributes key
///    events to focused nodes.
///  * [FocusTraversalPolicy], an object used to determine how to move the focus
///    to other nodes.
///  * [FocusTraversalGroup], a widget used to configure the focus traversal
///    policy for a widget subtree.
class FocusScope extends Focus {
  /// Creates a widget that manages a [FocusScopeNode].
  ///
  /// The [child] argument is required and must not be null.
  ///
  /// The [autofocus] argument must not be null.
  const FocusScope({
    super.key,
    FocusScopeNode? node,
    super.parentNode,
    required super.child,
    super.autofocus,
    super.onFocusChange,
    super.canRequestFocus,
    super.skipTraversal,
    super.onKeyEvent,
    super.onKey,
    super.debugLabel,
  })  : super(
          focusNode: node,
        );

  /// Creates a FocusScope widget that uses the given [focusScopeNode] as the
  /// source of truth for attributes on the node, rather than the attributes of
  /// this widget.
  const factory FocusScope.withExternalFocusNode({
    Key? key,
    required Widget child,
    required FocusScopeNode focusScopeNode,
    FocusNode? parentNode,
    bool autofocus,
    ValueChanged<bool>? onFocusChange,
  })  = _FocusScopeWithExternalFocusNode;

  /// Returns the [FocusScopeNode] of the [FocusScope] that most tightly
  /// encloses the given [context].
  ///
  /// If this node doesn't have a [Focus] widget ancestor, then the
  /// [FocusManager.rootScope] is returned.
  ///
  /// The [context] argument must not be null.
  static FocusScopeNode of(BuildContext context) {
    final _FocusInheritedScope? marker = context.dependOnInheritedWidgetOfExactType<_FocusInheritedScope>();
    return marker?.notifier?.nearestScope ?? context.owner!.focusManager.rootScope;
  }

  @override
  State<Focus> createState() => _FocusScopeState();
}

// Implements the behavior differences when the FocusScope.withExternalFocusNode
// constructor is used.
class _FocusScopeWithExternalFocusNode extends FocusScope {
  const _FocusScopeWithExternalFocusNode({
    super.key,
    required super.child,
    required FocusScopeNode focusScopeNode,
    super.parentNode,
    super.autofocus,
    super.onFocusChange,
  }) : super(
    node: focusScopeNode,
  );

  @override
  bool get _usingExternalFocus => true;
  @override
  FocusOnKeyEventCallback? get onKeyEvent => focusNode!.onKeyEvent;
  @override
  FocusOnKeyCallback? get onKey => focusNode!.onKey;
  @override
  bool get canRequestFocus => focusNode!.canRequestFocus;
  @override
  bool get skipTraversal => focusNode!.skipTraversal;
  @override
  bool get descendantsAreFocusable => focusNode!.descendantsAreFocusable;
  @override
  bool get descendantsAreTraversable => focusNode!.descendantsAreTraversable;
  @override
  String? get debugLabel => focusNode!.debugLabel;
}

class _FocusScopeState extends _FocusState {
  @override
  FocusScopeNode _createNode() {
    return FocusScopeNode(
      debugLabel: widget.debugLabel,
      canRequestFocus: widget.canRequestFocus,
      skipTraversal: widget.skipTraversal,
    );
  }

  @override
  Widget build(BuildContext context) {
    _focusAttachment!.reparent(parent: widget.parentNode);
    return Semantics(
      explicitChildNodes: true,
      child: _FocusInheritedScope(
        node: focusNode,
        child: widget.child,
      ),
    );
  }
}

// The InheritedWidget for Focus and FocusScope.
class _FocusInheritedScope extends InheritedNotifier<FocusNode> {
  const _FocusInheritedScope({
    required FocusNode node,
    required super.child,
  })  : super(notifier: node);
}

/// A widget that controls whether or not the descendants of this widget are
/// focusable.
///
/// Does not affect the value of [Focus.canRequestFocus] on the descendants.
///
/// See also:
///
///  * [Focus], a widget for adding and managing a [FocusNode] in the widget tree.
///  * [FocusTraversalGroup], a widget that groups widgets for focus traversal,
///    and can also be used in the same way as this widget by setting its
///    `descendantsAreFocusable` attribute.
class ExcludeFocus extends StatelessWidget {
  /// Const constructor for [ExcludeFocus] widget.
  ///
  /// The [excluding] argument must not be null.
  ///
  /// The [child] argument is required, and must not be null.
  const ExcludeFocus({
    super.key,
    this.excluding = true,
    required this.child,
  });

  /// If true, will make this widget's descendants unfocusable.
  ///
  /// Defaults to true.
  ///
  /// If any descendants are focused when this is set to true, they will be
  /// unfocused. When [excluding] is set to false again, they will not be
  /// refocused, although they will be able to accept focus again.
  ///
  /// Does not affect the value of [FocusNode.canRequestFocus] on the
  /// descendants.
  ///
  /// See also:
  ///
  /// * [Focus.descendantsAreFocusable], the attribute of a [Focus] widget that
  ///   controls this same property for focus widgets.
  /// * [FocusTraversalGroup], a widget used to group together and configure the
  ///   focus traversal policy for a widget subtree that has a
  ///   `descendantsAreFocusable` parameter to conditionally block focus for a
  ///   subtree.
  final bool excluding;

  /// The child widget of this [ExcludeFocus].
  ///
  /// {@macro flutter.widgets.ProxyWidget.child}
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Focus(
      canRequestFocus: false,
      skipTraversal: true,
      includeSemantics: false,
      descendantsAreFocusable: !excluding,
      child: child,
    );
  }
}
