// 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';
library;

import 'dart:async';
import 'dart:math' as math show max;

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';

import 'actions.dart';
import 'basic.dart';
import 'constants.dart';
import 'editable_text.dart';
import 'focus_manager.dart';
import 'framework.dart';
import 'inherited_notifier.dart';
import 'localizations.dart';
import 'media_query.dart';
import 'overlay.dart';
import 'shortcuts.dart';
import 'tap_region.dart';
import 'view.dart';

// Examples can assume:
// late BuildContext context;

/// The type of the [RawAutocomplete] callback which computes the list of
/// optional completions for the widget's field, based on the text the user has
/// entered so far.
///
/// See also:
///
///   * [RawAutocomplete.optionsBuilder], which is of this type.
typedef AutocompleteOptionsBuilder<T extends Object> =
    FutureOr<Iterable<T>> Function(TextEditingValue textEditingValue);

/// The type of the callback used by the [RawAutocomplete] widget to indicate
/// that the user has selected an option.
///
/// See also:
///
///   * [RawAutocomplete.onSelected], which is of this type.
typedef AutocompleteOnSelected<T extends Object> = void Function(T option);

/// The type of the [RawAutocomplete] callback which returns a [Widget] that
/// displays the specified [options] and calls [onSelected] if the user
/// selects an option.
///
/// The returned widget from this callback will be wrapped in an
/// [AutocompleteHighlightedOption] inherited widget. This will allow
/// this callback to determine which option is currently highlighted for
/// keyboard navigation.
///
/// See also:
///
///   * [RawAutocomplete.optionsViewBuilder], which is of this type.
typedef AutocompleteOptionsViewBuilder<T extends Object> =
    Widget Function(
      BuildContext context,
      AutocompleteOnSelected<T> onSelected,
      Iterable<T> options,
    );

/// The type of the Autocomplete callback which returns the widget that
/// contains the input [TextField] or [TextFormField].
///
/// See also:
///
///   * [RawAutocomplete.fieldViewBuilder], which is of this type.
typedef AutocompleteFieldViewBuilder =
    Widget Function(
      BuildContext context,
      TextEditingController textEditingController,
      FocusNode focusNode,
      VoidCallback onFieldSubmitted,
    );

/// The type of the [RawAutocomplete] callback that converts an option value to
/// a string which can be displayed in the widget's options menu.
///
/// See also:
///
///   * [RawAutocomplete.displayStringForOption], which is of this type.
typedef AutocompleteOptionToString<T extends Object> = String Function(T option);

/// A direction in which to open the options-view overlay.
///
/// See also:
///
///  * [RawAutocomplete.optionsViewOpenDirection], which is of this type.
///  * [RawAutocomplete.optionsViewBuilder] to specify how to build the
///    selectable-options widget.
///  * [RawAutocomplete.fieldViewBuilder] to optionally specify how to build the
///    corresponding field widget.
enum OptionsViewOpenDirection {
  /// Open upward.
  ///
  /// The bottom edge of the options view will align with the top edge
  /// of the text field built by [RawAutocomplete.fieldViewBuilder].
  up,

  /// Open downward.
  ///
  /// The top edge of the options view will align with the bottom edge
  /// of the text field built by [RawAutocomplete.fieldViewBuilder].
  down,

  /// Open in the direction with the most available space within the overlay.
  ///
  /// The available space is calculated as the distance from the field's top
  /// edge to the overlay's top edge (for upward opening) or from the field's
  /// bottom edge to the overlay's bottom edge (for downward opening).
  ///
  /// If both directions have the same available space, the options view opens
  /// downward.
  mostSpace,
}

// TODO(justinmc): Mention AutocompleteCupertino when it is implemented.
/// {@template flutter.widgets.RawAutocomplete.RawAutocomplete}
/// A widget for helping the user make a selection by entering some text and
/// choosing from among a list of options.
///
/// The user's text input is received in a field built with the
/// [fieldViewBuilder] parameter. The options to be displayed are determined
/// using [optionsBuilder] and rendered with [optionsViewBuilder].
///
/// The options view opens when the field gains focus or when the field's text
/// changes, as long as [optionsBuilder] returns at least one option. The options
/// view closes when the user selects an option, when there are no matching
/// options, or when the field loses focus.
/// {@endtemplate}
///
/// This is a core framework widget with very basic UI.
///
/// {@tool dartpad}
/// This example shows how to create a very basic autocomplete widget using the
/// [fieldViewBuilder] and [optionsViewBuilder] parameters.
///
/// ** See code in examples/api/lib/widgets/autocomplete/raw_autocomplete.0.dart **
/// {@end-tool}
///
/// The type parameter T represents the type of the options. Most commonly this
/// is a String, as in the example above. However, it's also possible to use
/// another type with a `toString` method, or a custom [displayStringForOption].
/// Options will be compared using `==`, so it may be beneficial to override
/// [Object.==] and [Object.hashCode] for custom types.
///
/// {@tool dartpad}
/// This example is similar to the previous example, but it uses a custom T data
/// type instead of directly using String.
///
/// ** See code in examples/api/lib/widgets/autocomplete/raw_autocomplete.1.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This example shows the use of RawAutocomplete in a form.
///
/// ** See code in examples/api/lib/widgets/autocomplete/raw_autocomplete.2.dart **
/// {@end-tool}
///
/// See also:
///
///  * [Autocomplete], which is a Material-styled implementation that is based
/// on RawAutocomplete.
class RawAutocomplete<T extends Object> extends StatefulWidget {
  /// Create an instance of RawAutocomplete.
  ///
  /// [displayStringForOption], [optionsBuilder] and [optionsViewBuilder] must
  /// not be null.
  const RawAutocomplete({
    super.key,
    required this.optionsViewBuilder,
    required this.optionsBuilder,
    this.optionsViewOpenDirection = OptionsViewOpenDirection.down,
    this.displayStringForOption = defaultStringForOption,
    this.fieldViewBuilder,
    this.focusNode,
    this.onSelected,
    this.textEditingController,
    this.initialValue,
  }) : assert(
         fieldViewBuilder != null ||
             (key != null && focusNode != null && textEditingController != null),
         'Pass in a fieldViewBuilder, or otherwise create a separate field and pass in the FocusNode, TextEditingController, and a key. Use the key with RawAutocomplete.onFieldSubmitted.',
       ),
       assert((focusNode == null) == (textEditingController == null)),
       assert(
         !(textEditingController != null && initialValue != null),
         'textEditingController and initialValue cannot be simultaneously defined.',
       );

  /// {@template flutter.widgets.RawAutocomplete.fieldViewBuilder}
  /// Builds the field whose input is used to get the options.
  ///
  /// Pass the provided [TextEditingController] to the field built here so that
  /// RawAutocomplete can listen for changes.
  /// {@endtemplate}
  ///
  /// If this parameter is null, then a [SizedBox.shrink] is built instead.
  /// For how that pattern can be useful, see [textEditingController].
  final AutocompleteFieldViewBuilder? fieldViewBuilder;

  /// The [FocusNode] that is used for the text field.
  ///
  /// {@template flutter.widgets.RawAutocomplete.split}
  /// The main purpose of this parameter is to allow the use of a separate text
  /// field located in another part of the widget tree instead of the text
  /// field built by [fieldViewBuilder]. For example, it may be desirable to
  /// place the text field in the AppBar and the options below in the main body.
  ///
  /// When following this pattern, [fieldViewBuilder] can be omitted,
  /// so that a text field is not drawn where it would normally be.
  /// A separate text field can be created elsewhere, and a
  /// FocusNode and TextEditingController can be passed both to that text field
  /// and to RawAutocomplete.
  ///
  /// {@tool dartpad}
  /// This examples shows how to create an autocomplete widget with the text
  /// field in the AppBar and the results in the main body of the app.
  ///
  /// ** See code in examples/api/lib/widgets/autocomplete/raw_autocomplete.focus_node.0.dart **
  /// {@end-tool}
  /// {@endtemplate}
  ///
  /// If this parameter is not null, then [textEditingController] must also be
  /// non-null.
  final FocusNode? focusNode;

  /// {@template flutter.widgets.RawAutocomplete.optionsViewBuilder}
  /// Builds the selectable options widgets from a list of options objects.
  ///
  /// The options are displayed floating below or above the field inside of an
  /// [Overlay], not at the same place in the widget tree as [RawAutocomplete].
  /// To control whether it opens upward or downward, use
  /// [optionsViewOpenDirection].
  ///
  /// In order to track which item is highlighted by keyboard navigation, the
  /// resulting options will be wrapped in an inherited
  /// [AutocompleteHighlightedOption] widget.
  /// Inside this callback, the index of the highlighted option can be obtained
  /// from [AutocompleteHighlightedOption.of] to display the highlighted option
  /// with a visual highlight to indicate it will be the option selected from
  /// the keyboard.
  ///
  /// {@endtemplate}
  final AutocompleteOptionsViewBuilder<T> optionsViewBuilder;

  /// {@template flutter.widgets.RawAutocomplete.optionsViewOpenDirection}
  /// Determines the direction in which to open the options view.
  ///
  /// Defaults to [OptionsViewOpenDirection.down].
  /// {@endtemplate}
  final OptionsViewOpenDirection optionsViewOpenDirection;

  /// {@template flutter.widgets.RawAutocomplete.displayStringForOption}
  /// Returns the string to display in the field when the option is selected.
  ///
  /// This is useful when using a custom T type and the string to display is
  /// different than the string to search by.
  ///
  /// If not provided, will use `option.toString()`.
  /// {@endtemplate}
  final AutocompleteOptionToString<T> displayStringForOption;

  /// {@template flutter.widgets.RawAutocomplete.onSelected}
  /// Called when an option is selected by the user.
  /// {@endtemplate}
  final AutocompleteOnSelected<T>? onSelected;

  /// {@template flutter.widgets.RawAutocomplete.optionsBuilder}
  /// A function that returns the current selectable options objects given the
  /// current TextEditingValue.
  /// {@endtemplate}
  final AutocompleteOptionsBuilder<T> optionsBuilder;

  /// The [TextEditingController] that is used for the text field.
  ///
  /// {@macro flutter.widgets.RawAutocomplete.split}
  ///
  /// If this parameter is not null, then [focusNode] must also be non-null.
  final TextEditingController? textEditingController;

  /// {@template flutter.widgets.RawAutocomplete.initialValue}
  /// The initial value to use for the text field.
  /// {@endtemplate}
  ///
  /// Setting the initial value does not notify [textEditingController]'s
  /// listeners, and thus will not cause the options UI to appear.
  ///
  /// This parameter is ignored if [textEditingController] is defined.
  final TextEditingValue? initialValue;

  /// Calls [AutocompleteFieldViewBuilder]'s onFieldSubmitted callback for the
  /// RawAutocomplete widget indicated by the given [GlobalKey].
  ///
  /// This is not typically used unless a custom field is implemented instead of
  /// using [fieldViewBuilder]. In the typical case, the onFieldSubmitted
  /// callback is passed via the [AutocompleteFieldViewBuilder] signature. When
  /// not using fieldViewBuilder, the same callback can be called by using this
  /// static method.
  ///
  /// See also:
  ///
  ///  * [focusNode] and [textEditingController], which contain a code example
  ///    showing how to create a separate field outside of fieldViewBuilder.
  static void onFieldSubmitted<T extends Object>(GlobalKey key) {
    final rawAutocomplete = key.currentState! as _RawAutocompleteState<T>;
    rawAutocomplete._onFieldSubmitted();
  }

  /// The default way to convert an option to a string in
  /// [displayStringForOption].
  ///
  /// Uses the `toString` method of the given `option`.
  static String defaultStringForOption(Object? option) {
    return option.toString();
  }

  @override
  State<RawAutocomplete<T>> createState() => _RawAutocompleteState<T>();
}

class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>> {
  final OverlayPortalController _optionsViewController = OverlayPortalController(
    debugLabel: '_RawAutocompleteState',
  );

  // The number of options to scroll by "page", such as when using the page
  // up/down keys.
  static const int _pageSize = 4;

  /// Whether the field currently has focus.
  ///
  /// This is used to determine whether the focus state has changed.
  late bool _hasFocus;

  /// Whether an option is currently being selected.
  bool _selecting = false;

  TextEditingController? _internalTextEditingController;
  TextEditingController get _textEditingController {
    return widget.textEditingController ??
        (_internalTextEditingController ??= TextEditingController()..addListener(_onChangedField));
  }

  FocusNode? _internalFocusNode;
  FocusNode get _focusNode {
    return widget.focusNode ?? (_internalFocusNode ??= FocusNode()..addListener(_onFocusChange));
  }

  late final Map<Type, CallbackAction<Intent>> _actionMap = <Type, CallbackAction<Intent>>{
    AutocompletePreviousOptionIntent: _AutocompleteCallbackAction<AutocompletePreviousOptionIntent>(
      onInvoke: _highlightPreviousOption,
      isEnabledCallback: () => _canShowOptionsView,
    ),
    AutocompleteNextOptionIntent: _AutocompleteCallbackAction<AutocompleteNextOptionIntent>(
      onInvoke: _highlightNextOption,
      isEnabledCallback: () => _canShowOptionsView,
    ),
    AutocompleteFirstOptionIntent: _AutocompleteCallbackAction<AutocompleteFirstOptionIntent>(
      onInvoke: _highlightFirstOption,
      isEnabledCallback: () => _canShowOptionsView,
    ),
    AutocompleteLastOptionIntent: _AutocompleteCallbackAction<AutocompleteLastOptionIntent>(
      onInvoke: _highlightLastOption,
      isEnabledCallback: () => _canShowOptionsView,
    ),
    AutocompleteNextPageOptionIntent: _AutocompleteCallbackAction<AutocompleteNextPageOptionIntent>(
      onInvoke: _highlightNextPageOption,
      isEnabledCallback: () => _canShowOptionsView,
    ),
    AutocompletePreviousPageOptionIntent:
        _AutocompleteCallbackAction<AutocompletePreviousPageOptionIntent>(
          onInvoke: _highlightPreviousPageOption,
          isEnabledCallback: () => _canShowOptionsView,
        ),
    DismissIntent: CallbackAction<DismissIntent>(onInvoke: _hideOptions),
  };

  Iterable<T> _options = Iterable<T>.empty();
  T? _selection;
  // Set the initial value to null so when this widget gets focused for the first
  // time it will try to run the options view builder.
  String? _lastFieldText;
  final ValueNotifier<int> _highlightedOptionIndex = ValueNotifier<int>(0);

  static const Map<ShortcutActivator, Intent> _appleShortcuts = <ShortcutActivator, Intent>{
    SingleActivator(LogicalKeyboardKey.arrowUp, meta: true): AutocompleteFirstOptionIntent(),
    SingleActivator(LogicalKeyboardKey.arrowDown, meta: true): AutocompleteLastOptionIntent(),
  };

  static const Map<ShortcutActivator, Intent> _nonAppleShortcuts = <ShortcutActivator, Intent>{
    SingleActivator(LogicalKeyboardKey.arrowUp, control: true): AutocompleteFirstOptionIntent(),
    SingleActivator(LogicalKeyboardKey.arrowDown, control: true): AutocompleteLastOptionIntent(),
  };

  static const Map<ShortcutActivator, Intent> _commonShortcuts = <ShortcutActivator, Intent>{
    SingleActivator(LogicalKeyboardKey.arrowUp): AutocompletePreviousOptionIntent(),
    SingleActivator(LogicalKeyboardKey.arrowDown): AutocompleteNextOptionIntent(),
    SingleActivator(LogicalKeyboardKey.pageUp): AutocompletePreviousPageOptionIntent(),
    SingleActivator(LogicalKeyboardKey.pageDown): AutocompleteNextPageOptionIntent(),
  };

  static Map<ShortcutActivator, Intent> get _shortcuts => <ShortcutActivator, Intent>{
    ..._commonShortcuts,
    ...switch (defaultTargetPlatform) {
      TargetPlatform.iOS => _appleShortcuts,
      TargetPlatform.macOS => _appleShortcuts,
      TargetPlatform.android => _nonAppleShortcuts,
      TargetPlatform.linux => _nonAppleShortcuts,
      TargetPlatform.windows => _nonAppleShortcuts,
      TargetPlatform.fuchsia => _nonAppleShortcuts,
    },
  };

  /// The options view is considered eligible to show only while the field has
  /// focus and there is at least one option to display.
  bool get _canShowOptionsView => _focusNode.hasFocus && _options.isNotEmpty;

  void _onFocusChange() {
    if (_focusNode.hasFocus != _hasFocus) {
      _hasFocus = _focusNode.hasFocus;
      // Gaining focus can open the options view (if there are options). Losing
      // focus always closes it.
      _updateOptionsViewVisibility();
    }
  }

  /// Shows the options view when the field is focused and there is at least one
  /// option to display; otherwise hides the options view.
  void _updateOptionsViewVisibility() {
    if (_canShowOptionsView) {
      _optionsViewController.show();
    } else {
      _optionsViewController.hide();
    }
  }

  void _announceSemantics(bool resultsAvailable) {
    if (!MediaQuery.supportsAnnounceOf(context)) {
      return;
    }
    final WidgetsLocalizations localizations = WidgetsLocalizations.of(context);
    final String optionsHint = resultsAvailable
        ? localizations.searchResultsFound
        : localizations.noResultsFound;
    SemanticsService.sendAnnouncement(View.of(context), optionsHint, localizations.textDirection);
  }

  // Assigning an ID to every call of _onChangedField is necessary to avoid a
  // situation where _options is updated by an older call when multiple
  // _onChangedField calls are running simultaneously.
  int _onChangedCallId = 0;
  // Called when _textEditingController changes.
  Future<void> _onChangedField() async {
    // During a selection, changes to the field text should not trigger
    // options update.
    if (_selecting) {
      return;
    }
    final TextEditingValue value = _textEditingController.value;

    // Makes sure that options change only when content of the field changes.
    var shouldUpdateOptions = false;
    if (value.text != _lastFieldText) {
      shouldUpdateOptions = true;
      _onChangedCallId += 1;
    }
    _lastFieldText = value.text;
    final int callId = _onChangedCallId;
    final Iterable<T> options = await widget.optionsBuilder(value);

    if (!mounted) {
      return;
    }

    // Makes sure that previous call results do not replace new ones.
    if (callId != _onChangedCallId || !shouldUpdateOptions) {
      return;
    }
    if (_options.isEmpty != options.isEmpty) {
      _announceSemantics(options.isNotEmpty);
    }
    _options = options;
    _updateHighlight(_highlightedOptionIndex.value);
    final T? selection = _selection;
    if (selection != null && value.text != widget.displayStringForOption(selection)) {
      _selection = null;
    }

    _updateOptionsViewVisibility();
  }

  // Called from fieldViewBuilder when the user submits the field.
  void _onFieldSubmitted() {
    if (_optionsViewController.isShowing) {
      _select(_options.elementAt(_highlightedOptionIndex.value));
    }
  }

  // Select the given option and update the widget.
  void _select(T nextSelection) {
    if (nextSelection == _selection) {
      return;
    }
    _selecting = true;
    _selection = nextSelection;
    final String selectionString = widget.displayStringForOption(nextSelection);
    _textEditingController.value = TextEditingValue(
      selection: TextSelection.collapsed(offset: selectionString.length),
      text: selectionString,
    );
    widget.onSelected?.call(nextSelection);
    if (_optionsViewController.isShowing) {
      _optionsViewController.hide(); // Close the options view after a selection is made.
    }
    _selecting = false;
  }

  void _updateHighlight(int nextIndex) {
    _highlightedOptionIndex.value = _options.isEmpty ? 0 : nextIndex.clamp(0, _options.length - 1);
  }

  void _highlightPreviousOption(AutocompletePreviousOptionIntent intent) {
    _highlightOption(_highlightedOptionIndex.value - 1);
  }

  void _highlightNextOption(AutocompleteNextOptionIntent intent) {
    _highlightOption(_highlightedOptionIndex.value + 1);
  }

  void _highlightFirstOption(AutocompleteFirstOptionIntent intent) {
    _highlightOption(0);
  }

  void _highlightLastOption(AutocompleteLastOptionIntent intent) {
    _highlightOption(_options.length - 1);
  }

  void _highlightNextPageOption(AutocompleteNextPageOptionIntent intent) {
    _highlightOption(_highlightedOptionIndex.value + _pageSize);
  }

  void _highlightPreviousPageOption(AutocompletePreviousPageOptionIntent intent) {
    _highlightOption(_highlightedOptionIndex.value - _pageSize);
  }

  void _highlightOption(int index) {
    assert(_canShowOptionsView);
    _updateOptionsViewVisibility();
    assert(_optionsViewController.isShowing);
    _updateHighlight(index);
  }

  Object? _hideOptions(DismissIntent intent) {
    if (_optionsViewController.isShowing) {
      _optionsViewController.hide();
      return null;
    } else {
      return Actions.invoke(context, intent);
    }
  }

  // A big enough height for about one item in the default
  // Autocomplete.optionsViewBuilder. The assumption is that the user likely
  // wants the list of options to move to stay on the screen rather than get any
  // smaller than this. Allows Autocomplete to work when it has very little
  // screen height available (as in b/317115348) by positioning itself on top of
  // the field, while in other cases to size itself based on the height under
  // the field.
  static const double _kMinUsableHeight = kMinInteractiveDimension;

  Widget _buildOptionsView(BuildContext context, OverlayChildLayoutInfo layoutInfo) {
    if (layoutInfo.childPaintTransform.determinant() == 0.0) {
      // The child is not visible.
      return const SizedBox.shrink();
    }
    final Size fieldSize = layoutInfo.childSize;
    final Matrix4 invertTransform = layoutInfo.childPaintTransform.clone()..invert();

    final EdgeInsets mediaQueryPadding = MediaQuery.paddingOf(context);
    final EdgeInsets viewInsets = MediaQuery.viewInsetsOf(context);

    final Rect overlayRect = mediaQueryPadding.deflateRect(
      viewInsets.deflateRect(Offset.zero & layoutInfo.overlaySize),
    );

    // This may not work well if the paint transform has rotation in it.
    // MatrixUtils.transformRect returns the bounding rect of the rotated overlay
    // rect.
    final Rect overlayRectInField = MatrixUtils.transformRect(invertTransform, overlayRect);

    final double spaceAbove = -overlayRectInField.top;
    final double spaceBelow = overlayRectInField.bottom - fieldSize.height;
    final bool opensUp = switch (widget.optionsViewOpenDirection) {
      OptionsViewOpenDirection.up => true,
      OptionsViewOpenDirection.down => false,
      OptionsViewOpenDirection.mostSpace => spaceAbove > spaceBelow,
    };

    final double optionsViewMaxHeight = opensUp
        ? -overlayRectInField.top
        : overlayRectInField.bottom - fieldSize.height;

    final optionsViewBoundingBox = Size(
      fieldSize.width,
      math.max(optionsViewMaxHeight, _kMinUsableHeight),
    );

    final double originY = opensUp
        ? overlayRectInField.top
        : overlayRectInField.bottom - optionsViewBoundingBox.height;

    final Matrix4 transform = layoutInfo.childPaintTransform.clone()
      ..translateByDouble(0.0, originY, 0, 1);
    final Widget child = Builder(
      builder: (BuildContext context) => widget.optionsViewBuilder(context, _select, _options),
    );
    return Transform(
      transform: transform,
      child: Align(
        alignment: Alignment.topLeft,
        child: ConstrainedBox(
          constraints: BoxConstraints.tight(optionsViewBoundingBox),
          child: Align(
            alignment: opensUp ? AlignmentDirectional.bottomStart : AlignmentDirectional.topStart,
            child: TextFieldTapRegion(
              child: AutocompleteHighlightedOption(
                highlightIndexNotifier: _highlightedOptionIndex,
                child: child,
              ),
            ),
          ),
        ),
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    final TextEditingController initialController =
        widget.textEditingController ??
        (_internalTextEditingController = TextEditingController.fromValue(widget.initialValue));
    initialController.addListener(_onChangedField);
    _hasFocus = _focusNode.hasFocus;
    widget.focusNode?.addListener(_onFocusChange);
  }

  @override
  void didUpdateWidget(RawAutocomplete<T> oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (!identical(oldWidget.textEditingController, widget.textEditingController)) {
      oldWidget.textEditingController?.removeListener(_onChangedField);
      if (oldWidget.textEditingController == null) {
        _internalTextEditingController?.dispose();
        _internalTextEditingController = null;
      }
      widget.textEditingController?.addListener(_onChangedField);
    }
    if (!identical(oldWidget.focusNode, widget.focusNode)) {
      oldWidget.focusNode?.removeListener(_updateOptionsViewVisibility);
      if (oldWidget.focusNode == null) {
        _internalFocusNode?.dispose();
        _internalFocusNode = null;
      }
      widget.focusNode?.addListener(_updateOptionsViewVisibility);
    }
  }

  @override
  void dispose() {
    widget.textEditingController?.removeListener(_onChangedField);
    _internalTextEditingController?.dispose();
    widget.focusNode?.removeListener(_updateOptionsViewVisibility);
    _internalFocusNode?.dispose();
    _highlightedOptionIndex.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final Widget fieldView =
        widget.fieldViewBuilder?.call(
          context,
          _textEditingController,
          _focusNode,
          _onFieldSubmitted,
        ) ??
        // Horizontally expand to make sure the options view's width won't be zero.
        const SizedBox(width: double.infinity, height: 0.0);
    return OverlayPortal.overlayChildLayoutBuilder(
      controller: _optionsViewController,
      overlayChildBuilder: _buildOptionsView,
      child: TextFieldTapRegion(
        child: Shortcuts(
          shortcuts: _shortcuts,
          child: Actions(actions: _actionMap, child: fieldView),
        ),
      ),
    );
  }
}

class _AutocompleteCallbackAction<T extends Intent> extends CallbackAction<T> {
  _AutocompleteCallbackAction({required super.onInvoke, required this.isEnabledCallback});

  // The enabled state determines whether the action will consume the
  // key shortcut or let it continue on to the underlying text field.
  // They should only be enabled when the options are showing so shortcuts
  // can be used to navigate them.
  final bool Function() isEnabledCallback;

  @override
  bool isEnabled(covariant T intent) => isEnabledCallback();

  @override
  bool consumesKey(covariant T intent) => isEnabled(intent);
}

/// An [Intent] to highlight the previous option in the autocomplete list.
class AutocompletePreviousOptionIntent extends Intent {
  /// Creates an instance of AutocompletePreviousOptionIntent.
  const AutocompletePreviousOptionIntent();
}

/// An [Intent] to highlight the next option in the autocomplete list.
class AutocompleteNextOptionIntent extends Intent {
  /// Creates an instance of AutocompleteNextOptionIntent.
  const AutocompleteNextOptionIntent();
}

/// An [Intent] to highlight the first option in the autocomplete list.
class AutocompleteFirstOptionIntent extends Intent {
  /// Creates an instance of AutocompleteFirstOptionIntent.
  const AutocompleteFirstOptionIntent();
}

/// An [Intent] to highlight the last option in the autocomplete list.
class AutocompleteLastOptionIntent extends Intent {
  /// Creates an instance of AutocompleteLastOptionIntent.
  const AutocompleteLastOptionIntent();
}

/// An [Intent] to highlight the option one page after the currently highlighted
/// option in the autocomplete list.
class AutocompleteNextPageOptionIntent extends Intent {
  /// Creates an instance of AutocompleteNextPageOptionIntent.
  const AutocompleteNextPageOptionIntent();
}

/// An [Intent] to highlight the option one page before the currently
/// highlighted option in the autocomplete list.
class AutocompletePreviousPageOptionIntent extends Intent {
  /// Creates an instance of AutocompletePreviousPageOptionIntent.
  const AutocompletePreviousPageOptionIntent();
}

/// An inherited widget used to indicate which autocomplete option should be
/// highlighted for keyboard navigation.
///
/// The `RawAutocomplete` widget will wrap the options view generated by the
/// `optionsViewBuilder` with this widget to provide the highlighted option's
/// index to the builder.
///
/// In the builder callback the index of the highlighted option can be obtained
/// by using the static [of] method:
///
/// ```dart
/// int highlightedIndex = AutocompleteHighlightedOption.of(context);
/// ```
///
/// which can then be used to tell which option should be given a visual
/// indication that will be the option selected with the keyboard.
class AutocompleteHighlightedOption extends InheritedNotifier<ValueNotifier<int>> {
  /// Create an instance of AutocompleteHighlightedOption inherited widget.
  const AutocompleteHighlightedOption({
    super.key,
    required ValueNotifier<int> highlightIndexNotifier,
    required super.child,
  }) : super(notifier: highlightIndexNotifier);

  /// Returns the index of the highlighted option from the closest
  /// [AutocompleteHighlightedOption] ancestor.
  ///
  /// If there is no ancestor, it returns 0.
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// int highlightedIndex = AutocompleteHighlightedOption.of(context);
  /// ```
  static int of(BuildContext context) {
    return context
            .dependOnInheritedWidgetOfExactType<AutocompleteHighlightedOption>()
            ?.notifier
            ?.value ??
        0;
  }
}
