// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:math' as math;
import 'dart:ui' show TextAffinity, TextPosition;

import 'package:characters/characters.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'
    show Clipboard, ClipboardData, TextLayoutMetrics, TextRange;

import 'editable_text.dart';

/// The recipient of a [TextEditingAction].
///
/// TextEditingActions will only be enabled when an implementer of this class is
/// focused.
///
/// See also:
///
///   * [EditableTextState], which implements this and is the most typical
///     target of a TextEditingAction.
abstract class TextEditingActionTarget {
  /// Whether the characters in the field are obscured from the user.
  ///
  /// When true, the entire contents of the field are treated as one word.
  bool get obscureText;

  /// Whether the field currently in a read-only state.
  ///
  /// When true, [textEditingValue]'s text may not be modified, but its selection can be.
  bool get readOnly;

  /// Whether the [textEditingValue]'s selection can be modified.
  bool get selectionEnabled;

  /// Provides information about the text that is the target of this action.
  ///
  /// See also:
  ///
  /// * [EditableTextState.renderEditable], which overrides this.
  TextLayoutMetrics get textLayoutMetrics;

  /// The [TextEditingValue] expressed in this field.
  TextEditingValue get textEditingValue;

  // Holds the last cursor location the user selected in the case the user tries
  // to select vertically past the end or beginning of the field. If they do,
  // then we need to keep the old cursor location so that we can go back to it
  // if they change their minds. Only used for moving selection up and down in a
  // multiline text field when selecting using the keyboard.
  int _cursorResetLocation = -1;

  // Whether we should reset the location of the cursor in the case the user
  // tries to select vertically past the end or beginning of the field. If they
  // do, then we need to keep the old cursor location so that we can go back to
  // it if they change their minds. Only used for resetting selection up and
  // down in a multiline text field when selecting using the keyboard.
  bool _wasSelectingVerticallyWithKeyboard = false;

  /// Called when assuming that the text layout is in sync with
  /// [textEditingValue].
  ///
  /// Can be overridden to assert that this is a valid assumption.
  void debugAssertLayoutUpToDate();

  /// Returns the index into the string of the next character boundary after the
  /// given index.
  ///
  /// The character boundary is determined by the characters package, so
  /// surrogate pairs and extended grapheme clusters are considered.
  ///
  /// The index must be between 0 and string.length, inclusive. If given
  /// string.length, string.length is returned.
  ///
  /// Setting includeWhitespace to false will only return the index of non-space
  /// characters.
  @visibleForTesting
  static int nextCharacter(int index, String string, [bool includeWhitespace = true]) {
    assert(index >= 0 && index <= string.length);
    if (index == string.length) {
      return string.length;
    }

    final CharacterRange range = CharacterRange.at(string, 0, index);
    // If index is not on a character boundary, return the next character
    // boundary.
    if (range.current.length != index) {
      return range.current.length;
    }

    range.expandNext();
    if (!includeWhitespace) {
      range.expandWhile((String character) {
        return TextLayoutMetrics.isWhitespace(character.codeUnitAt(0));
      });
    }
    return range.current.length;
  }

  /// Returns the index into the string of the previous character boundary
  /// before the given index.
  ///
  /// The character boundary is determined by the characters package, so
  /// surrogate pairs and extended grapheme clusters are considered.
  ///
  /// The index must be between 0 and string.length, inclusive. If index is 0,
  /// 0 will be returned.
  ///
  /// Setting includeWhitespace to false will only return the index of non-space
  /// characters.
  @visibleForTesting
  static int previousCharacter(int index, String string, [bool includeWhitespace = true]) {
    assert(index >= 0 && index <= string.length);
    if (index == 0) {
      return 0;
    }

    final CharacterRange range = CharacterRange.at(string, 0, index);
    // If index is not on a character boundary, return the previous character
    // boundary.
    if (range.current.length != index) {
      range.dropLast();
      return range.current.length;
    }

    range.dropLast();
    if (!includeWhitespace) {
      while (range.currentCharacters.isNotEmpty
          && TextLayoutMetrics.isWhitespace(range.charactersAfter.first.codeUnitAt(0))) {
        range.dropLast();
      }
    }
    return range.current.length;
  }

  /// {@template flutter.widgets.TextEditingActionTarget.setSelection}
  /// Called to update the [TextSelection] in the current [TextEditingValue].
  /// {@endtemplate}
  void setSelection(TextSelection nextSelection, SelectionChangedCause cause) {
    if (nextSelection == textEditingValue.selection) {
      return;
    }
    setTextEditingValue(
      textEditingValue.copyWith(selection: nextSelection),
      cause,
    );
  }

  /// {@template flutter.widgets.TextEditingActionTarget.setTextEditingValue}
  /// Called to update the current [TextEditingValue].
  /// {@endtemplate}
  void setTextEditingValue(TextEditingValue newValue, SelectionChangedCause cause);

  // Extend the current selection to the end of the field.
  //
  // If selectionEnabled is false, keeps the selection collapsed and moves it to
  // the end.
  //
  // See also:
  //
  //   * _extendSelectionToStart
  void _extendSelectionToEnd(SelectionChangedCause cause) {
    if (textEditingValue.selection.extentOffset == textEditingValue.text.length) {
      return;
    }

    final TextSelection nextSelection = textEditingValue.selection.copyWith(
      extentOffset: textEditingValue.text.length,
    );
    return setSelection(nextSelection, cause);
  }

  // Extend the current selection to the start of the field.
  //
  // If selectionEnabled is false, keeps the selection collapsed and moves it to
  // the start.
  //
  // The given [SelectionChangedCause] indicates the cause of this change and
  // will be passed to [setSelection].
  //
  // See also:
  //
  //   * _extendSelectionToEnd
  void _extendSelectionToStart(SelectionChangedCause cause) {
    if (!selectionEnabled) {
      return moveSelectionToStart(cause);
    }

    setSelection(textEditingValue.selection.extendTo(const TextPosition(
      offset: 0,
      affinity: TextAffinity.upstream,
    )), cause);
  }

  // Return the offset at the start of the nearest word to the left of the
  // given offset.
  int _getLeftByWord(int offset, [bool includeWhitespace = true]) {
    // If the offset is already all the way left, there is nothing to do.
    if (offset <= 0) {
      return offset;
    }

    // If we can just return the start of the text without checking for a word.
    if (offset == 1) {
      return 0;
    }

    final int startPoint = previousCharacter(
        offset, textEditingValue.text, includeWhitespace);
    final TextRange word =
        textLayoutMetrics.getWordBoundary(TextPosition(offset: startPoint, affinity: textEditingValue.selection.affinity));
    return word.start;
  }

  /// Return the offset at the end of the nearest word to the right of the given
  /// offset.
  int _getRightByWord(int offset, [bool includeWhitespace = true]) {
    // If the selection is already all the way right, there is nothing to do.
    if (offset == textEditingValue.text.length) {
      return offset;
    }

    // If we can just return the end of the text without checking for a word.
    if (offset == textEditingValue.text.length - 1 || offset == textEditingValue.text.length) {
      return textEditingValue.text.length;
    }

    final int startPoint = includeWhitespace ||
            !TextLayoutMetrics.isWhitespace(textEditingValue.text.codeUnitAt(offset))
        ? offset
        : nextCharacter(offset, textEditingValue.text, includeWhitespace);
    final TextRange nextWord =
        textLayoutMetrics.getWordBoundary(TextPosition(offset: startPoint, affinity: textEditingValue.selection.affinity));
    return nextWord.end;
  }

  // Deletes the current non-empty selection.
  //
  // If the selection is currently non-empty, this method deletes the selected
  // text. Otherwise this method does nothing.
  TextEditingValue _deleteNonEmptySelection() {
    assert(textEditingValue.selection.isValid);
    assert(!textEditingValue.selection.isCollapsed);

    final String textBefore = textEditingValue.selection.textBefore(textEditingValue.text);
    final String textAfter = textEditingValue.selection.textAfter(textEditingValue.text);
    final TextSelection newSelection = TextSelection.collapsed(
      offset: textEditingValue.selection.start,
      affinity: textEditingValue.selection.affinity,
    );
    final TextRange newComposingRange = !textEditingValue.composing.isValid || textEditingValue.composing.isCollapsed
      ? TextRange.empty
      : TextRange(
        start: textEditingValue.composing.start - (textEditingValue.composing.start - textEditingValue.selection.start).clamp(0, textEditingValue.selection.end - textEditingValue.selection.start),
        end: textEditingValue.composing.end - (textEditingValue.composing.end - textEditingValue.selection.start).clamp(0, textEditingValue.selection.end - textEditingValue.selection.start),
      );

    return TextEditingValue(
      text: textBefore + textAfter,
      selection: newSelection,
      composing: newComposingRange,
    );
  }

  /// Returns a new TextEditingValue representing a deletion from the current
  /// [selection] to the given index, inclusively.
  ///
  /// If the selection is not collapsed, deletes the selection regardless of the
  /// given index.
  ///
  /// The composing region, if any, will also be adjusted to remove the deleted
  /// characters.
  TextEditingValue _deleteTo(TextPosition position) {
    assert(textEditingValue.selection != null);

    if (!textEditingValue.selection.isValid) {
      return textEditingValue;
    }
    if (!textEditingValue.selection.isCollapsed) {
      return _deleteNonEmptySelection();
    }
    if (position.offset == textEditingValue.selection.extentOffset) {
      return textEditingValue;
    }

    final TextRange deletion = TextRange(
      start: math.min(position.offset, textEditingValue.selection.extentOffset),
      end: math.max(position.offset, textEditingValue.selection.extentOffset),
    );
    final String deleted = deletion.textInside(textEditingValue.text);
    if (deletion.textInside(textEditingValue.text).isEmpty) {
      return textEditingValue;
    }

    final int charactersDeletedBeforeComposingStart =
        (textEditingValue.composing.start - deletion.start).clamp(0, deleted.length);
    final int charactersDeletedBeforeComposingEnd =
        (textEditingValue.composing.end - deletion.start).clamp(0, deleted.length);
    final TextRange nextComposingRange = !textEditingValue.composing.isValid || textEditingValue.composing.isCollapsed
      ? TextRange.empty
      : TextRange(
        start: textEditingValue.composing.start - charactersDeletedBeforeComposingStart,
        end: textEditingValue.composing.end - charactersDeletedBeforeComposingEnd,
      );

    return TextEditingValue(
      text: deletion.textBefore(textEditingValue.text) + deletion.textAfter(textEditingValue.text),
      selection: TextSelection.collapsed(
        offset: deletion.start,
        affinity: position.affinity,
      ),
      composing: nextComposingRange,
    );
  }

  /// Deletes backwards from the current selection.
  ///
  /// If the selection is collapsed, deletes a single character before the
  /// cursor.
  ///
  /// If the selection is not collapsed, deletes the selection.
  ///
  /// If [readOnly] is true or the selection is invalid, does nothing.
  ///
  /// {@template flutter.widgets.TextEditingActionTarget.cause}
  /// The given [SelectionChangedCause] indicates the cause of this change and
  /// will be passed to [setSelection].
  /// {@endtemplate}
  ///
  /// See also:
  ///
  ///   * [deleteForward], which is same but in the opposite direction.
  void delete(SelectionChangedCause cause) {
    if (readOnly) {
      return;
    }
    if (!textEditingValue.selection.isValid) {
      return;
    }

    // `delete` does not depend on the text layout, and the boundary analysis is
    // done using the `previousCharacter` method instead of ICU, we can keep
    // deleting without having to layout the text. For this reason, we can
    // directly delete the character before the caret in the controller.
    final String textBefore = textEditingValue.selection.textBefore(textEditingValue.text);
    final int characterBoundary = previousCharacter(
      textBefore.length,
      textBefore,
    );
    final TextPosition position = TextPosition(offset: characterBoundary);
    setTextEditingValue(_deleteTo(position), cause);
  }

  /// Deletes a word backwards from the current selection.
  ///
  /// If the selection is collapsed, deletes a word before the cursor.
  ///
  /// If the selection is not collapsed, deletes the selection.
  ///
  /// If [readOnly] is true or the selection is invalid, does nothing.
  ///
  /// If [obscureText] is true, it treats the whole text content as a single
  /// word.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// {@template flutter.widgets.TextEditingActionTarget.whiteSpace}
  /// By default, includeWhitespace is set to true, meaning that whitespace can
  /// be considered a word in itself.  If set to false, the selection will be
  /// extended past any whitespace and the first word following the whitespace.
  /// {@endtemplate}
  ///
  /// See also:
  ///
  ///   * [deleteForwardByWord], which is same but in the opposite direction.
  void deleteByWord(SelectionChangedCause cause,
      [bool includeWhitespace = true]) {
    if (readOnly) {
      return;
    }
    if (!textEditingValue.selection.isValid) {
      return;
    }

    if (obscureText) {
      // When the text is obscured, the whole thing is treated as one big line.
      return deleteToStart(cause);
    }

    final String textBefore = textEditingValue.selection.textBefore(textEditingValue.text);
    final int characterBoundary =
        _getLeftByWord(textBefore.length, includeWhitespace);
    final TextEditingValue nextValue = _deleteTo(TextPosition(offset: characterBoundary));

    setTextEditingValue(nextValue, cause);
  }

  /// Deletes a line backwards from the current selection.
  ///
  /// If the selection is collapsed, deletes a line before the cursor.
  ///
  /// If the selection is not collapsed, deletes the selection.
  ///
  /// If [obscureText] is true, it treats the whole text content as
  /// a single word.
  ///
  /// If [readOnly] is true or the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [deleteForwardByLine], which is same but in the opposite direction.
  void deleteByLine(SelectionChangedCause cause) {
    if (readOnly) {
      return;
    }
    if (!textEditingValue.selection.isValid) {
      return;
    }

    // When there is a line break, line delete shouldn't do anything
    final String textBefore = textEditingValue.selection.textBefore(textEditingValue.text);
    final bool isPreviousCharacterBreakLine =
        textBefore.codeUnitAt(textBefore.length - 1) == 0x0A;
    if (isPreviousCharacterBreakLine) {
      return;
    }

    // When the text is obscured, the whole thing is treated as one big line.
    if (obscureText) {
      return deleteToStart(cause);
    }

    final TextSelection line = textLayoutMetrics.getLineAtOffset(
      TextPosition(offset: textBefore.length - 1),
    );

    setTextEditingValue(_deleteTo(TextPosition(offset: line.start)), cause);
  }

  /// Deletes in the forward direction.
  ///
  /// If the selection is collapsed, deletes a single character after the
  /// cursor.
  ///
  /// If the selection is not collapsed, deletes the selection.
  ///
  /// If [readOnly] is true or the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [delete], which is the same but in the opposite direction.
  void deleteForward(SelectionChangedCause cause) {
    if (readOnly) {
      return;
    }
    if (!textEditingValue.selection.isValid) {
      return;
    }

    final String textAfter = textEditingValue.selection.textAfter(textEditingValue.text);
    final int characterBoundary = nextCharacter(0, textAfter);
    setTextEditingValue(_deleteTo(TextPosition(offset: textEditingValue.selection.end + characterBoundary)), cause);
  }

  /// Deletes a word in the forward direction from the current selection.
  ///
  /// If the selection is collapsed, deletes a word after the cursor.
  ///
  /// If the selection is not collapsed, deletes the selection.
  ///
  /// If [readOnly] is true or the selection is invalid, does nothing.
  ///
  /// If [obscureText] is true, it treats the whole text content as
  /// a single word.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.whiteSpace}
  ///
  /// See also:
  ///
  ///   * [deleteByWord], which is same but in the opposite direction.
  void deleteForwardByWord(SelectionChangedCause cause,
      [bool includeWhitespace = true]) {
    if (readOnly) {
      return;
    }
    if (!textEditingValue.selection.isValid) {
      return;
    }

    if (obscureText) {
      // When the text is obscured, the whole thing is treated as one big word.
      return deleteToEnd(cause);
    }

    final String textBefore = textEditingValue.selection.textBefore(textEditingValue.text);
    final int characterBoundary = _getRightByWord(textBefore.length, includeWhitespace);
    final TextEditingValue nextValue = _deleteTo(TextPosition(offset: characterBoundary));

    setTextEditingValue(nextValue, cause);
  }

  /// Deletes a line in the forward direction from the current selection.
  ///
  /// If the selection is collapsed, deletes a line after the cursor.
  ///
  /// If the selection is not collapsed, deletes the selection.
  ///
  /// If [readOnly] is true or the selection is invalid, does nothing.
  ///
  /// If [obscureText] is true, it treats the whole text content as
  /// a single word.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [deleteByLine], which is same but in the opposite direction.
  void deleteForwardByLine(SelectionChangedCause cause) {
    if (readOnly) {
      return;
    }
    if (!textEditingValue.selection.isValid) {
      return;
    }

    if (obscureText) {
      // When the text is obscured, the whole thing is treated as one big line.
      return deleteToEnd(cause);
    }


    // When there is a line break, it shouldn't do anything.
    final String textAfter = textEditingValue.selection.textAfter(textEditingValue.text);
    final bool isNextCharacterBreakLine = textAfter.codeUnitAt(0) == 0x0A;
    if (isNextCharacterBreakLine) {
      return;
    }

    final String textBefore = textEditingValue.selection.textBefore(textEditingValue.text);
    final TextSelection line = textLayoutMetrics.getLineAtOffset(
      TextPosition(offset: textBefore.length),
    );

    setTextEditingValue(_deleteTo(TextPosition(offset: line.end)), cause);
  }

  /// Deletes the from the current collapsed selection to the end of the field.
  ///
  /// The given SelectionChangedCause indicates the cause of this change and
  /// will be passed to setSelection.
  ///
  /// If [readOnly] is true or the selection is invalid, does nothing.
  ///
  /// See also:
  ///   * [deleteToStart]
  void deleteToEnd(SelectionChangedCause cause) {
    assert(textEditingValue.selection.isCollapsed);
    if (readOnly) {
      return;
    }
    if (!textEditingValue.selection.isValid) {
      return;
    }

    setTextEditingValue(_deleteTo(TextPosition(offset: textEditingValue.text.length)), cause);
  }

  /// Deletes the from the current collapsed selection to the start of the field.
  ///
  /// The given SelectionChangedCause indicates the cause of this change and
  /// will be passed to setSelection.
  ///
  /// If [readOnly] is true or the selection is invalid, does nothing.
  ///
  /// See also:
  ///   * [deleteToEnd]
  void deleteToStart(SelectionChangedCause cause) {
    assert(textEditingValue.selection.isCollapsed);
    if (readOnly) {
      return;
    }
    if (!textEditingValue.selection.isValid) {
      return;
    }

    setTextEditingValue(_deleteTo(const TextPosition(offset: 0)), cause);
  }

  /// Expand the current selection to the end of the field.
  ///
  /// The selection will never shrink. The [TextSelection.extentOffset] will
  // always be at the end of the field, regardless of the original order of
  /// [TextSelection.baseOffset] and [TextSelection.extentOffset].
  ///
  /// If [selectionEnabled] is false, keeps the selection collapsed and moves it
  /// to the end.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [expandSelectionToStart], which is same but in the opposite direction.
  void expandSelectionToEnd(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    if (!selectionEnabled) {
      return moveSelectionToEnd(cause);
    }

    final TextPosition nextPosition = TextPosition(
      offset: textEditingValue.text.length,
    );
    setSelection(textEditingValue.selection.expandTo(nextPosition, true), cause);
  }

  /// Expand the current selection to the start of the field.
  ///
  /// The selection will never shrink. The [TextSelection.extentOffset] will
  /// always be at the start of the field, regardless of the original order of
  /// [TextSelection.baseOffset] and [TextSelection.extentOffset].
  ///
  /// If [selectionEnabled] is false, keeps the selection collapsed and moves it
  /// to the start.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [expandSelectionToEnd], which is the same but in the opposite
  ///     direction.
  void expandSelectionToStart(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    if (!selectionEnabled) {
      return moveSelectionToStart(cause);
    }

    const TextPosition nextPosition = TextPosition(
      offset: 0,
      affinity: TextAffinity.upstream,
    );
    setSelection(textEditingValue.selection.expandTo(nextPosition, true), cause);
  }

  /// Expand the current selection to the smallest selection that includes the
  /// start of the line.
  ///
  /// The selection will never shrink. The upper offset will be expanded to the
  /// beginning of its line, and the original order of baseOffset and
  /// [TextSelection.extentOffset] will be preserved.
  ///
  /// If [selectionEnabled] is false, keeps the selection collapsed and moves it
  /// left by line.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [expandSelectionRightByLine], which is the same but in the opposite
  ///     direction.
  void expandSelectionLeftByLine(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    if (!selectionEnabled) {
      return moveSelectionLeftByLine(cause);
    }

    // If the lowest edge of the selection is at the start of a line, don't do
    // anything.
    // TODO(justinmc): Support selection with multiple TextAffinities.
    // https://github.com/flutter/flutter/issues/88135
    final TextSelection currentLine = textLayoutMetrics.getLineAtOffset(
      TextPosition(
        offset: textEditingValue.selection.start,
        affinity: textEditingValue.selection.isCollapsed
            ? textEditingValue.selection.affinity
            : TextAffinity.downstream,
      ),
    );
    if (currentLine.baseOffset == textEditingValue.selection.start) {
      return;
    }

    setSelection(textEditingValue.selection.expandTo(TextPosition(
      offset: currentLine.baseOffset,
      affinity: textEditingValue.selection.affinity,
    )), cause);
  }

  /// Expand the current selection to the smallest selection that includes the
  /// end of the line.
  ///
  /// The selection will never shrink. The lower offset will be expanded to the
  /// end of its line and the original order of [TextSelection.baseOffset] and
  /// [TextSelection.extentOffset] will be preserved.
  ///
  /// If [selectionEnabled] is false, keeps the selection collapsed and moves it
  /// right by line.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [expandSelectionLeftByLine], which is the same but in the opposite
  ///     direction.
  void expandSelectionRightByLine(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    if (!selectionEnabled) {
      return moveSelectionRightByLine(cause);
    }

    // If greatest edge is already at the end of a line, don't do anything.
    // TODO(justinmc): Support selection with multiple TextAffinities.
    // https://github.com/flutter/flutter/issues/88135
    final TextSelection currentLine = textLayoutMetrics.getLineAtOffset(
      TextPosition(
        offset: textEditingValue.selection.end,
        affinity: textEditingValue.selection.isCollapsed
            ? textEditingValue.selection.affinity
            : TextAffinity.upstream,
      ),
    );
    if (currentLine.extentOffset == textEditingValue.selection.end) {
      return;
    }

    final TextSelection nextSelection = textEditingValue.selection.expandTo(
      TextPosition(
        offset: currentLine.extentOffset,
        affinity: TextAffinity.upstream,
      ),
    );
    setSelection(nextSelection, cause);
  }

  /// Keeping selection's [TextSelection.baseOffset] fixed, move the
  /// [TextSelection.extentOffset] down by one line.
  ///
  /// If selectionEnabled is false, keeps the selection collapsed and just
  /// moves it down.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [extendSelectionUp], which is same but in the opposite direction.
  void extendSelectionDown(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    if (!selectionEnabled) {
      return moveSelectionDown(cause);
    }

    // If the selection is collapsed at the end of the field already, then
    // nothing happens.
    if (textEditingValue.selection.isCollapsed &&
        textEditingValue.selection.extentOffset >= textEditingValue.text.length) {
      return;
    }

    int index =
        textLayoutMetrics.getTextPositionBelow(textEditingValue.selection.extent).offset;

    if (index == textEditingValue.selection.extentOffset) {
      index = textEditingValue.text.length;
      _wasSelectingVerticallyWithKeyboard = true;
    } else if (_wasSelectingVerticallyWithKeyboard) {
      index = _cursorResetLocation;
      _wasSelectingVerticallyWithKeyboard = false;
    } else {
      _cursorResetLocation = index;
    }

    final TextPosition nextPosition = TextPosition(
      offset: index,
      affinity: textEditingValue.selection.affinity,
    );
    setSelection(textEditingValue.selection.extendTo(nextPosition), cause);
  }

  /// If [selectionEnabled] is false, keeps the selection collapsed and moves it
  /// left.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [extendSelectionRight], which is same but in the opposite direction.
  void extendSelectionLeft(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    if (!selectionEnabled) {
      return moveSelectionLeft(cause);
    }

    // If the selection is already all the way left, there is nothing to do.
    if (textEditingValue.selection.extentOffset <= 0) {
      return;
    }

    final int previousExtent = previousCharacter(
      textEditingValue.selection.extentOffset,
      textEditingValue.text,
    );

    final int distance = textEditingValue.selection.extentOffset - previousExtent;
    _cursorResetLocation -= distance;
    setSelection(textEditingValue.selection.extendTo(TextPosition(offset: previousExtent, affinity: textEditingValue.selection.affinity)), cause);
  }

  /// Extend the current selection to the start of
  /// [TextSelection.extentOffset]'s line.
  ///
  /// Uses [TextSelection.baseOffset] as a pivot point and doesn't change it.
  /// If [TextSelection.extentOffset] is right of [TextSelection.baseOffset],
  /// then the selection will be collapsed.
  ///
  /// If [selectionEnabled] is false, keeps the selection collapsed and moves it
  /// left by line.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [extendSelectionRightByLine], which is same but in the opposite
  ///     direction.
  ///   * [expandSelectionRightByLine], which strictly grows the selection
  ///     regardless of the order.
  void extendSelectionLeftByLine(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    if (!selectionEnabled) {
      return moveSelectionLeftByLine(cause);
    }

    // When going left, we want to skip over any whitespace before the line,
    // so we go back to the first non-whitespace before asking for the line
    // bounds, since getLineAtOffset finds the line boundaries without
    // including whitespace (like the newline).
    final int startPoint = previousCharacter(
        textEditingValue.selection.extentOffset, textEditingValue.text, false);
    final TextSelection selectedLine = textLayoutMetrics.getLineAtOffset(
      TextPosition(offset: startPoint),
    );

    late final TextSelection nextSelection;
    // If the extent and base offsets would reverse order, then instead the
    // selection collapses.
    if (textEditingValue.selection.extentOffset > textEditingValue.selection.baseOffset) {
      nextSelection = textEditingValue.selection.copyWith(
        extentOffset: textEditingValue.selection.baseOffset,
      );
    } else {
      nextSelection = textEditingValue.selection.extendTo(TextPosition(
        offset: selectedLine.baseOffset,
      ));
    }

    setSelection(nextSelection, cause);
  }

  /// Keeping selection's [TextSelection.baseOffset] fixed, move the
  /// [TextSelection.extentOffset] right.
  ///
  /// If [selectionEnabled] is false, keeps the selection collapsed and moves it
  /// right.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [extendSelectionLeft], which is same but in the opposite direction.
  void extendSelectionRight(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    if (!selectionEnabled) {
      return moveSelectionRight(cause);
    }

    // If the selection is already all the way right, there is nothing to do.
    if (textEditingValue.selection.extentOffset >= textEditingValue.text.length) {
      return;
    }
    final int nextExtent = nextCharacter(
        textEditingValue.selection.extentOffset, textEditingValue.text);

    final int distance = nextExtent - textEditingValue.selection.extentOffset;
    _cursorResetLocation += distance;
    setSelection(textEditingValue.selection.extendTo(TextPosition(offset: nextExtent, affinity: textEditingValue.selection.affinity)), cause);
  }

  /// Extend the current selection to the end of [TextSelection.extentOffset]'s
  /// line.
  ///
  /// Uses [TextSelection.baseOffset] as a pivot point and doesn't change it. If
  /// [TextSelection.extentOffset] is left of [TextSelection.baseOffset], then
  /// collapses the selection.
  ///
  /// If [selectionEnabled] is false, keeps the selection collapsed and moves it
  /// right by line.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [extendSelectionLeftByLine], which is same but in the opposite
  ///     direction.
  ///   * [expandSelectionRightByLine], which strictly grows the selection
  ///     regardless of the order.
  void extendSelectionRightByLine(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    if (!selectionEnabled) {
      return moveSelectionRightByLine(cause);
    }

    final int startPoint = nextCharacter(
        textEditingValue.selection.extentOffset, textEditingValue.text, false);
    final TextSelection selectedLine = textLayoutMetrics.getLineAtOffset(
      TextPosition(offset: startPoint),
    );

    // If the extent and base offsets would reverse order, then instead the
    // selection collapses.
    late final TextSelection nextSelection;
    if (textEditingValue.selection.extentOffset < textEditingValue.selection.baseOffset) {
      nextSelection = textEditingValue.selection.copyWith(
        extentOffset: textEditingValue.selection.baseOffset,
      );
    } else {
      nextSelection = textEditingValue.selection.extendTo(TextPosition(
        offset: selectedLine.extentOffset,
        affinity: TextAffinity.upstream,
      ));
    }

    setSelection(nextSelection, cause);
  }

  /// Extend the current selection to the previous start of a word.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.whiteSpace}
  ///
  /// {@template flutter.widgets.TextEditingActionTarget.stopAtReversal}
  /// The `stopAtReversal` parameter is false by default, meaning that it's
  /// ok for the base and extent to flip their order here. If set to true, then
  /// the selection will collapse when it would otherwise reverse its order. A
  /// selection that is already collapsed is not affected by this parameter.
  /// {@endtemplate}
  ///
  /// See also:
  ///
  ///   * [extendSelectionRightByWord], which is the same but in the opposite
  ///     direction.
  void extendSelectionLeftByWord(SelectionChangedCause cause,
      [bool includeWhitespace = true, bool stopAtReversal = false]) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    // When the text is obscured, the whole thing is treated as one big word.
    if (obscureText) {
      return _extendSelectionToStart(cause);
    }

    debugAssertLayoutUpToDate();
    // If the selection is already all the way left, there is nothing to do.
    if (textEditingValue.selection.isCollapsed && textEditingValue.selection.extentOffset <= 0) {
      return;
    }

    final int leftOffset =
        _getLeftByWord(textEditingValue.selection.extentOffset, includeWhitespace);

    late final TextSelection nextSelection;
    if (stopAtReversal &&
        textEditingValue.selection.extentOffset > textEditingValue.selection.baseOffset &&
        leftOffset < textEditingValue.selection.baseOffset) {
      nextSelection = textEditingValue.selection.extendTo(TextPosition(offset: textEditingValue.selection.baseOffset));
    } else {
      nextSelection = textEditingValue.selection.extendTo(TextPosition(offset: leftOffset, affinity: textEditingValue.selection.affinity));
    }

    if (nextSelection == textEditingValue.selection) {
      return;
    }
    setSelection(nextSelection, cause);
  }

  /// Extend the current selection to the next end of a word.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.whiteSpace}
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.stopAtReversal}
  ///
  /// See also:
  ///
  ///   * [extendSelectionLeftByWord], which is the same but in the opposite
  ///     direction.
  void extendSelectionRightByWord(SelectionChangedCause cause,
      [bool includeWhitespace = true, bool stopAtReversal = false]) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    debugAssertLayoutUpToDate();
    // When the text is obscured, the whole thing is treated as one big word.
    if (obscureText) {
      return _extendSelectionToEnd(cause);
    }

    // If the selection is already all the way right, there is nothing to do.
    if (textEditingValue.selection.isCollapsed &&
        textEditingValue.selection.extentOffset == textEditingValue.text.length) {
      return;
    }

    final int rightOffset =
        _getRightByWord(textEditingValue.selection.extentOffset, includeWhitespace);

    late final TextSelection nextSelection;
    if (stopAtReversal &&
        textEditingValue.selection.baseOffset > textEditingValue.selection.extentOffset &&
        rightOffset > textEditingValue.selection.baseOffset) {
      nextSelection = TextSelection.fromPosition(
        TextPosition(offset: textEditingValue.selection.baseOffset),
      );
    } else {
      nextSelection = textEditingValue.selection.extendTo(TextPosition(offset: rightOffset, affinity: textEditingValue.selection.affinity));
    }

    if (nextSelection == textEditingValue.selection) {
      return;
    }
    setSelection(nextSelection, cause);
  }

  /// Keeping selection's [TextSelection.baseOffset] fixed, move the
  /// [TextSelection.extentOffset] up by one
  /// line.
  ///
  /// If [selectionEnabled] is false, keeps the selection collapsed and moves it
  /// up.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [extendSelectionDown], which is the same but in the opposite
  ///     direction.
  void extendSelectionUp(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    if (!selectionEnabled) {
      return moveSelectionUp(cause);
    }

    // If the selection is collapsed at the beginning of the field already, then
    // nothing happens.
    if (textEditingValue.selection.isCollapsed && textEditingValue.selection.extentOffset <= 0.0) {
      return;
    }

    final TextPosition positionAbove =
        textLayoutMetrics.getTextPositionAbove(textEditingValue.selection.extent);
    late final TextSelection nextSelection;
    if (positionAbove.offset == textEditingValue.selection.extentOffset) {
      nextSelection = textEditingValue.selection.copyWith(
        extentOffset: 0,
        affinity: TextAffinity.upstream,
      );
      _wasSelectingVerticallyWithKeyboard = true;
    } else if (_wasSelectingVerticallyWithKeyboard) {
      nextSelection = textEditingValue.selection.copyWith(
        baseOffset: textEditingValue.selection.baseOffset,
        extentOffset: _cursorResetLocation,
      );
      _wasSelectingVerticallyWithKeyboard = false;
    } else {
      nextSelection = textEditingValue.selection.copyWith(
        baseOffset: textEditingValue.selection.baseOffset,
        extentOffset: positionAbove.offset,
        affinity: positionAbove.affinity,
      );
      _cursorResetLocation = nextSelection.extentOffset;
    }

    setSelection(nextSelection, cause);
  }

  /// Move the current selection to the leftmost point of the current line.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [moveSelectionRightByLine], which is the same but in the opposite
  ///     direction.
  void moveSelectionLeftByLine(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    // If already at the left edge of the line, do nothing.
    final TextSelection currentLine = textLayoutMetrics.getLineAtOffset(
      textEditingValue.selection.extent,
    );
    if (currentLine.baseOffset == textEditingValue.selection.extentOffset) {
      return;
    }

    // When going left, we want to skip over any whitespace before the line,
    // so we go back to the first non-whitespace before asking for the line
    // bounds, since getLineAtOffset finds the line boundaries without
    // including whitespace (like the newline).
    final int startPoint = previousCharacter(
        textEditingValue.selection.extentOffset, textEditingValue.text, false);
    final TextSelection selectedLine = textLayoutMetrics.getLineAtOffset(
      TextPosition(offset: startPoint),
    );
    final TextSelection nextSelection = TextSelection.fromPosition(TextPosition(
      offset: selectedLine.baseOffset,
    ));

    setSelection(nextSelection, cause);
  }

  /// Move the current selection to the next line.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [moveSelectionUp], which is the same but in the opposite direction.
  void moveSelectionDown(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    // If the selection is collapsed at the end of the field already, then
    // nothing happens.
    if (textEditingValue.selection.isCollapsed &&
        textEditingValue.selection.extentOffset >= textEditingValue.text.length) {
      return;
    }

    final TextPosition positionBelow =
        textLayoutMetrics.getTextPositionBelow(textEditingValue.selection.extent);

    late final TextSelection nextSelection;
    if (positionBelow.offset == textEditingValue.selection.extentOffset) {
      nextSelection = textEditingValue.selection.copyWith(
        baseOffset: textEditingValue.text.length,
        extentOffset: textEditingValue.text.length,
      );
    } else {
      nextSelection = TextSelection.fromPosition(positionBelow);
    }

    if (textEditingValue.selection.extentOffset == textEditingValue.text.length) {
      _wasSelectingVerticallyWithKeyboard = false;
    } else {
      _cursorResetLocation = nextSelection.extentOffset;
    }

    setSelection(nextSelection, cause);
  }

  /// Move the current selection left by one character.
  ///
  /// If it can't be moved left, do nothing.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [moveSelectionRight], which is the same but in the opposite direction.
  void moveSelectionLeft(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    // If the selection is already all the way left, there is nothing to do.
    if (textEditingValue.selection.isCollapsed && textEditingValue.selection.extentOffset <= 0) {
      return;
    }

    int previousExtent;
    if (textEditingValue.selection.start != textEditingValue.selection.end) {
      previousExtent = textEditingValue.selection.start;
    } else {
      previousExtent = previousCharacter(
          textEditingValue.selection.extentOffset, textEditingValue.text);
    }
    final TextSelection nextSelection = TextSelection.fromPosition(
      TextPosition(
        offset: previousExtent,
        affinity: textEditingValue.selection.affinity,
      ),
    );

    if (nextSelection == textEditingValue.selection) {
      return;
    }
    _cursorResetLocation -=
        textEditingValue.selection.extentOffset - nextSelection.extentOffset;
    setSelection(nextSelection, cause);
  }

  /// Move the current selection to the previous start of a word.
  ///
  /// A TextSelection that isn't collapsed will be collapsed and moved from the
  /// extentOffset.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.whiteSpace}
  ///
  /// See also:
  ///
  ///   * [moveSelectionRightByWord], which is the same but in the opposite
  ///     direction.
  void moveSelectionLeftByWord(SelectionChangedCause cause,
      [bool includeWhitespace = true]) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    // When the text is obscured, the whole thing is treated as one big word.
    if (obscureText) {
      return moveSelectionToStart(cause);
    }

    debugAssertLayoutUpToDate();
    // If the selection is already all the way left, there is nothing to do.
    if (textEditingValue.selection.isCollapsed && textEditingValue.selection.extentOffset <= 0) {
      return;
    }

    final int leftOffset =
        _getLeftByWord(textEditingValue.selection.extentOffset, includeWhitespace);
    final TextSelection nextSelection = TextSelection.fromPosition(TextPosition(offset: leftOffset, affinity: textEditingValue.selection.affinity));

    if (nextSelection == textEditingValue.selection) {
      return;
    }
    setSelection(nextSelection, cause);
  }

  /// Move the current selection to the right by one character.
  ///
  /// If the selection is invalid or it can't be moved right, do nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [moveSelectionLeft], which is the same but in the opposite direction.
  void moveSelectionRight(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    // If the selection is already all the way right, there is nothing to do.
    if (textEditingValue.selection.isCollapsed &&
        textEditingValue.selection.extentOffset >= textEditingValue.text.length) {
      return;
    }

    int nextExtent;
    if (textEditingValue.selection.start != textEditingValue.selection.end) {
      nextExtent = textEditingValue.selection.end;
    } else {
      nextExtent = nextCharacter(
          textEditingValue.selection.extentOffset, textEditingValue.text);
    }
    final TextSelection nextSelection = TextSelection.fromPosition(TextPosition(
      offset: nextExtent,
    ));

    if (nextSelection == textEditingValue.selection) {
      return;
    }
    setSelection(nextSelection, cause);
  }

  /// Move the current selection to the rightmost point of the current line.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [moveSelectionLeftByLine], which is the same but in the opposite
  ///     direction.
  void moveSelectionRightByLine(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    // If already at the right edge of the line, do nothing.
    final TextSelection currentLine = textLayoutMetrics.getLineAtOffset(
      textEditingValue.selection.extent,
    );
    if (currentLine.extentOffset == textEditingValue.selection.extentOffset) {
      return;
    }

    // When going right, we want to skip over any whitespace after the line,
    // so we go forward to the first non-whitespace character before asking
    // for the line bounds, since getLineAtOffset finds the line
    // boundaries without including whitespace (like the newline).
    final int startPoint = nextCharacter(
        textEditingValue.selection.extentOffset, textEditingValue.text, false);
    final TextSelection selectedLine = textLayoutMetrics.getLineAtOffset(
      TextPosition(
        offset: startPoint,
        affinity: TextAffinity.upstream,
      ),
    );
    final TextSelection nextSelection = TextSelection.fromPosition(TextPosition(
      offset: selectedLine.extentOffset,
      affinity: TextAffinity.upstream,
    ));
    setSelection(nextSelection, cause);
  }

  /// Move the current selection to the next end of a word.
  ///
  /// A TextSelection that isn't collapsed will be collapsed and moved from the
  /// extentOffset.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.whiteSpace}
  ///
  /// See also:
  ///
  ///   * [moveSelectionLeftByWord], which is the same but in the opposite
  ///     direction.
  void moveSelectionRightByWord(SelectionChangedCause cause,
      [bool includeWhitespace = true]) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    // When the text is obscured, the whole thing is treated as one big word.
    if (obscureText) {
      return moveSelectionToEnd(cause);
    }

    debugAssertLayoutUpToDate();
    // If the selection is already all the way right, there is nothing to do.
    if (textEditingValue.selection.isCollapsed &&
        textEditingValue.selection.extentOffset == textEditingValue.text.length) {
      return;
    }

    final int rightOffset =
        _getRightByWord(textEditingValue.selection.extentOffset, includeWhitespace);
    final TextSelection nextSelection = TextSelection.fromPosition(TextPosition(offset: rightOffset, affinity: textEditingValue.selection.affinity));

    if (nextSelection == textEditingValue.selection) {
      return;
    }
    setSelection(nextSelection, cause);
  }

  /// Move the current selection to the end of the field.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [moveSelectionToStart], which is the same but in the opposite
  ///     direction.
  void moveSelectionToEnd(SelectionChangedCause cause) {
    final TextPosition nextPosition = TextPosition(
      offset: textEditingValue.text.length,
    );
    setSelection(TextSelection.fromPosition(nextPosition), cause);
  }

  /// Move the current selection to the start of the field.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [moveSelectionToEnd], which is the same but in the opposite direction.
  void moveSelectionToStart(SelectionChangedCause cause) {
    const TextPosition nextPosition = TextPosition(
      offset: 0,
      affinity: TextAffinity.upstream,
    );
    setSelection(TextSelection.fromPosition(nextPosition), cause);
  }

  /// Move the current selection up by one line.
  ///
  /// If the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  ///
  /// See also:
  ///
  ///   * [moveSelectionDown], which is the same but in the opposite direction.
  void moveSelectionUp(SelectionChangedCause cause) {
    if (!textEditingValue.selection.isValid) {
      return;
    }
    final int nextIndex =
        textLayoutMetrics.getTextPositionAbove(textEditingValue.selection.extent).offset;

    if (nextIndex == textEditingValue.selection.extentOffset) {
      _wasSelectingVerticallyWithKeyboard = false;
      return moveSelectionToStart(cause);
    }
    _cursorResetLocation = nextIndex;

    setSelection(TextSelection.fromPosition(TextPosition(offset: nextIndex, affinity: textEditingValue.selection.affinity)), cause);
  }

  /// Select the entire text value.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  void selectAll(SelectionChangedCause cause) {
    setSelection(
      textEditingValue.selection.copyWith(
        baseOffset: 0,
        extentOffset: textEditingValue.text.length,
      ),
      cause,
    );
  }

  /// {@template flutter.widgets.TextEditingActionTarget.copySelection}
  /// Copy current selection to [Clipboard].
  /// {@endtemplate}
  ///
  /// If the selection is collapsed or invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  void copySelection(SelectionChangedCause cause) {
    final TextSelection selection = textEditingValue.selection;
    final String text = textEditingValue.text;
    assert(selection != null);
    if (selection.isCollapsed || !selection.isValid) {
      return;
    }
    Clipboard.setData(ClipboardData(text: selection.textInside(text)));
  }

  /// {@template flutter.widgets.TextEditingActionTarget.cutSelection}
  /// Cut current selection to Clipboard.
  /// {@endtemplate}
  ///
  /// If [readOnly] is true or the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  void cutSelection(SelectionChangedCause cause) {
    final TextSelection selection = textEditingValue.selection;
    if (readOnly || !selection.isValid) {
      return;
    }
    final String text = textEditingValue.text;
    assert(selection != null);
    if (selection.isCollapsed) {
      return;
    }
    Clipboard.setData(ClipboardData(text: selection.textInside(text)));
    setTextEditingValue(
      TextEditingValue(
        text: selection.textBefore(text) + selection.textAfter(text),
        selection: TextSelection.collapsed(
          offset: math.min(selection.start, selection.end),
          affinity: selection.affinity,
        ),
      ),
      cause,
    );
  }

  /// {@template flutter.widgets.TextEditingActionTarget.pasteText}
  /// Paste text from [Clipboard].
  /// {@endtemplate}
  ///
  /// If there is currently a selection, it will be replaced.
  ///
  /// If [readOnly] is true or the selection is invalid, does nothing.
  ///
  /// {@macro flutter.widgets.TextEditingActionTarget.cause}
  Future<void> pasteText(SelectionChangedCause cause) async {
    final TextSelection selection = textEditingValue.selection;
    if (readOnly || !selection.isValid) {
      return;
    }
    final String text = textEditingValue.text;
    assert(selection != null);
    if (!selection.isValid) {
      return;
    }
    // Snapshot the input before using `await`.
    // See https://github.com/flutter/flutter/issues/11427
    final ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain);
    if (data == null) {
      return;
    }
    setTextEditingValue(
      TextEditingValue(
        text: selection.textBefore(text) +
            data.text! +
            selection.textAfter(text),
        selection: TextSelection.collapsed(
          offset:
              math.min(selection.start, selection.end) + data.text!.length,
          affinity: selection.affinity,
        ),
      ),
      cause,
    );
  }
}
