// Copyright 2013 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:async';
import 'dart:math' as math;
import 'dart:typed_data';

import 'package:meta/meta.dart';
import 'package:ui/ui.dart' as ui;

import '../browser_detection.dart';
import '../dom.dart';
import '../embedder.dart';
import '../host_node.dart';
import '../platform_dispatcher.dart';
import '../safe_browser_api.dart';
import '../semantics.dart';
import '../services.dart';
import '../text/paragraph.dart';
import '../util.dart';
import 'autofill_hint.dart';
import 'composition_aware_mixin.dart';
import 'input_action.dart';
import 'input_type.dart';
import 'text_capitalization.dart';

/// Make the content editable span visible to facilitate debugging.
bool _debugVisibleTextEditing = false;

/// Set this to `true` to print when text input commands are scheduled and run.
bool _debugPrintTextInputCommands = false;

/// The `keyCode` of the "Enter" key.
const int _kReturnKeyCode = 13;

/// Offset in pixels to place an element outside of the screen.
const int offScreenOffset = -9999;

/// Blink and Webkit engines, bring an overlay on top of the text field when it
/// is autofilled.
bool browserHasAutofillOverlay() =>
    browserEngine == BrowserEngine.blink ||
    browserEngine == BrowserEngine.webkit;

/// `transparentTextEditing` class is configured to make the autofill overlay
/// transparent.
const String transparentTextEditingClass = 'transparentTextEditing';

void _emptyCallback(dynamic _) {}

/// The default [HostNode] that hosts all DOM required for text editing when a11y is not enabled.
@visibleForTesting
HostNode get defaultTextEditingRoot => flutterViewEmbedder.glassPaneShadow!;

/// These style attributes are constant throughout the life time of an input
/// element.
///
/// They are assigned once during the creation of the DOM element.
void _setStaticStyleAttributes(DomHTMLElement domElement) {
  domElement.classList.add(HybridTextEditing.textEditingClass);

  final DomCSSStyleDeclaration elementStyle = domElement.style;
  elementStyle
    // Prevent (forced-colors: active) from making our invisible text fields visible.
    // For more details, see: https://developer.mozilla.org/en-US/docs/Web/CSS/forced-color-adjust
    ..setProperty('forced-color-adjust', 'none')
    ..whiteSpace = 'pre-wrap'
    ..alignContent = 'center'
    ..position = 'absolute'
    ..top = '0'
    ..left = '0'
    ..padding = '0'
    ..opacity = '1'
    ..color = 'transparent'
    ..backgroundColor = 'transparent'
    ..background = 'transparent'
    // This property makes the input's blinking cursor transparent.
    ..caretColor = 'transparent'
    ..outline = 'none'
    ..border = 'none'
    ..resize = 'none'
    ..textShadow = 'none'
    ..overflow = 'hidden'
    ..transformOrigin = '0 0 0';

  if (browserHasAutofillOverlay()) {
    domElement.classList.add(transparentTextEditingClass);
  }

  if (_debugVisibleTextEditing) {
    elementStyle
      ..color = 'purple'
      ..outline = '1px solid purple';
  }
}

/// Sets attributes to hide autofill elements.
///
/// These style attributes are constant throughout the life time of an input
/// element.
///
/// They are assigned once during the creation of the DOM element.
void _hideAutofillElements(DomHTMLElement domElement,
    {bool isOffScreen = false}) {
  final DomCSSStyleDeclaration elementStyle = domElement.style;
  elementStyle
    ..whiteSpace = 'pre-wrap'
    ..alignContent = 'center'
    ..padding = '0'
    ..opacity = '1'
    ..color = 'transparent'
    ..backgroundColor = 'transparent'
    ..background = 'transparent'
    ..outline = 'none'
    ..border = 'none'
    ..resize = 'none'
    ..width = '0'
    ..height = '0'
    ..textShadow = 'transparent'
    ..transformOrigin = '0 0 0';

  if (isOffScreen) {
    elementStyle
      ..top = '${offScreenOffset}px'
      ..left = '${offScreenOffset}px';
  }

  if (browserHasAutofillOverlay()) {
    domElement.classList.add(transparentTextEditingClass);
  }

  /// This property makes the input's blinking cursor transparent.
  elementStyle.setProperty('caret-color', 'transparent');
}

/// Form that contains all the fields in the same AutofillGroup.
///
/// An [EngineAutofillForm] will only be constructed when autofill is enabled
/// (the default) on the current input field. See the [fromFrameworkMessage]
/// static method.
class EngineAutofillForm {
  EngineAutofillForm({
    required this.formElement,
    this.elements,
    this.items,
    this.formIdentifier = '',
  });

  final DomHTMLFormElement formElement;

  final Map<String, DomHTMLElement>? elements;

  final Map<String, AutofillInfo>? items;

  /// Identifier for the form.
  ///
  /// It is constructed by concatenating unique ids of input elements on the
  /// form.
  ///
  /// It is used for storing the form until submission.
  /// See [formsOnTheDom].
  final String formIdentifier;

  /// Creates an [EngineAutofillFrom] from the JSON representation of a Flutter
  /// framework `TextInputConfiguration` object.
  ///
  /// The `focusedElementAutofill` argument corresponds to the "autofill" field
  /// in a `TextInputConfiguration`. Not having this field indicates autofill
  /// is explicitly disabled on the text field by the developer.
  ///
  /// The `fields` argument corresponds to the "fields" field in a
  /// `TextInputConfiguration`.
  ///
  /// Returns null if autofill is disabled for the input field.
  static EngineAutofillForm? fromFrameworkMessage(
    Map<String, dynamic>? focusedElementAutofill,
    List<dynamic>? fields,
  ) {
    // Autofill value will be null if the developer explicitly disables it on
    // the input field.
    if (focusedElementAutofill == null) {
      return null;
    }

    // If there is only one text field in the autofill model, `fields` will be
    // null. `focusedElementAutofill` contains the information about the one
    // text field.
    final Map<String, DomHTMLElement> elements = <String, DomHTMLElement>{};
    final Map<String, AutofillInfo> items = <String, AutofillInfo>{};
    final DomHTMLFormElement formElement = createDomHTMLFormElement();

    // Validation is in the framework side.
    formElement.noValidate = true;
    formElement.method = 'post';
    formElement.action = '#';
    formElement.addEventListener('submit', allowInterop((DomEvent e) {
      e.preventDefault();
    }));

    _hideAutofillElements(formElement);

    // We keep the ids in a list then sort them later, in case the text fields'
    // locations are re-ordered on the framework side.
    final List<String> ids = List<String>.empty(growable: true);

    // The focused text editing element will not be created here.
    final AutofillInfo focusedElement =
        AutofillInfo.fromFrameworkMessage(focusedElementAutofill);

    if (fields != null) {
      for (final Map<String, dynamic> field in
          fields.cast<Map<String, dynamic>>()) {
        final Map<String, dynamic> autofillInfo = field.readJson('autofill');
        final AutofillInfo autofill = AutofillInfo.fromFrameworkMessage(
          autofillInfo,
          textCapitalization: TextCapitalizationConfig.fromInputConfiguration(
            field.readString('textCapitalization'),
          ),
        );

        ids.add(autofill.uniqueIdentifier);

        if (autofill.uniqueIdentifier != focusedElement.uniqueIdentifier) {
          final EngineInputType engineInputType = EngineInputType.fromName(
            field.readJson('inputType').readString('name'),
          );

          final DomHTMLElement htmlElement = engineInputType.createDomElement();
          autofill.editingState.applyToDomElement(htmlElement);
          autofill.applyToDomElement(htmlElement);
          _hideAutofillElements(htmlElement);

          items[autofill.uniqueIdentifier] = autofill;
          elements[autofill.uniqueIdentifier] = htmlElement;
          formElement.append(htmlElement);
        }
      }
    } else {
      // There is one input element in the form.
      ids.add(focusedElement.uniqueIdentifier);
    }

    ids.sort();
    final StringBuffer idBuffer = StringBuffer();

    // Add a separator between element identifiers.
    for (final String id in ids) {
      if (idBuffer.length > 0) {
        idBuffer.write('*');
      }
      idBuffer.write(id);
    }

    final String formIdentifier = idBuffer.toString();

    // If a form with the same Autofill elements is already on the dom, remove
    // it from DOM.
    final DomHTMLFormElement? form = formsOnTheDom[formIdentifier];
    form?.remove();

    // In order to submit the form when Framework sends a `TextInput.commit`
    // message, we add a submit button to the form.
    final DomHTMLInputElement submitButton = createDomHTMLInputElement();
    _hideAutofillElements(submitButton, isOffScreen: true);
    submitButton.className = 'submitBtn';
    submitButton.type = 'submit';

    formElement.append(submitButton);

    return EngineAutofillForm(
      formElement: formElement,
      elements: elements,
      items: items,
      formIdentifier: formIdentifier,
    );
  }

  void placeForm(DomHTMLElement mainTextEditingElement) {
    formElement.append(mainTextEditingElement);
    defaultTextEditingRoot.append(formElement);
  }

  void storeForm() {
    formsOnTheDom[formIdentifier] = formElement;
    _hideAutofillElements(formElement, isOffScreen: true);
  }

  /// Listens to `onInput` event on the form fields.
  ///
  /// Registering to the listeners could have been done in the constructor.
  /// On the other hand, overall for text editing there is already a lifecycle
  /// for subscriptions: All the subscriptions of the DOM elements are to the
  /// `subscriptions` property of [DefaultTextEditingStrategy].
  /// [TextEditingStrategy] manages all subscription lifecyle. All
  /// listeners with no exceptions are added during
  /// [TextEditingStrategy.addEventHandlers] method call and all
  /// listeners are removed during [TextEditingStrategy.disable] method call.
  List<DomSubscription> addInputEventListeners() {
    final Iterable<String> keys = elements!.keys;
    final List<DomSubscription> subscriptions = <DomSubscription>[];

    void addSubscriptionForKey(String key) {
        final DomElement element = elements![key]!;
        subscriptions.add(
            DomSubscription(element, 'input',
                allowInterop((DomEvent e) {
                  if (items![key] == null) {
                    throw StateError(
                        'AutofillInfo must have a valid uniqueIdentifier.');
                  } else {
                    final AutofillInfo autofillInfo = items![key]!;
                    handleChange(element, autofillInfo);
                  }
                })));
    }

    keys.forEach(addSubscriptionForKey);
    return subscriptions;
  }

  void handleChange(DomElement domElement, AutofillInfo autofillInfo) {
    final EditingState newEditingState = EditingState.fromDomElement(
        domElement as DomHTMLElement);

    _sendAutofillEditingState(autofillInfo.uniqueIdentifier, newEditingState);
  }

  /// Sends the 'TextInputClient.updateEditingStateWithTag' message to the framework.
  void _sendAutofillEditingState(String? tag, EditingState editingState) {
    EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
      'flutter/textinput',
      const JSONMethodCodec().encodeMethodCall(
        MethodCall(
          'TextInputClient.updateEditingStateWithTag',
          <dynamic>[
            0,
            <String?, dynamic>{tag: editingState.toFlutter()}
          ],
        ),
      ),
      _emptyCallback,
    );
  }
}

/// Autofill related values.
///
/// These values are to be used when a text field have autofill enabled.
@visibleForTesting
class AutofillInfo {
  AutofillInfo({
    required this.editingState,
    required this.uniqueIdentifier,
    required this.autofillHint,
    required this.textCapitalization,
    this.placeholder,
  });

  factory AutofillInfo.fromFrameworkMessage(Map<String, dynamic> autofill,
      {TextCapitalizationConfig textCapitalization =
          const TextCapitalizationConfig.defaultCapitalization()}) {
    assert(autofill != null);
    final String uniqueIdentifier = autofill.readString('uniqueIdentifier');
    final List<dynamic>? hintsList = autofill.tryList('hints');
    final String? firstHint = (hintsList == null || hintsList.isEmpty) ? null : hintsList.first as String;
    final EditingState editingState =
        EditingState.fromFrameworkMessage(autofill.readJson('editingValue'));
    return AutofillInfo(
      uniqueIdentifier: uniqueIdentifier,
      autofillHint: (firstHint != null) ? BrowserAutofillHints.instance.flutterToEngine(firstHint) : null,
      editingState: editingState,
      placeholder: autofill.tryString('hintText'),
      textCapitalization: textCapitalization,
    );
  }

  /// The current text and selection state of a text field.
  final EditingState editingState;

  /// Unique value set by the developer or generated by the framework.
  ///
  /// Used as id of the text field.
  ///
  /// An example an id generated by the framework: `EditableText-285283643`.
  final String uniqueIdentifier;

  /// Information on how should autofilled text capitalized.
  ///
  /// For example for [TextCapitalization.characters] each letter is converted
  /// to upper case.
  ///
  /// This value is not necessary for autofilling the focused element since
  /// [DefaultTextEditingStrategy.inputConfiguration] already has this
  /// information.
  ///
  /// On the other hand for the multi element forms, for the input elements
  /// other the focused field, we need to use this information.
  final TextCapitalizationConfig textCapitalization;

  /// The type of information expected in the field, specified by the developer.
  ///
  /// Used as a guidance to the browser as to the type of information expected
  /// in the field.
  /// See: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete
  final String? autofillHint;

  /// The optional hint text placed on the view that typically suggests what
  /// sort of input the field accepts, for example "enter your password here".
  ///
  /// If the developer does not specify any [autofillHints], the [placeholder]
  /// can be a useful indication to the platform autofill service as to what
  /// information is expected in this field.
  final String? placeholder;

  void applyToDomElement(DomHTMLElement domElement,
      {bool focusedElement = false}) {
    final String? autofillHint = this.autofillHint;
    final String? placeholder = this.placeholder;
    if (domInstanceOfString(domElement, 'HTMLInputElement')) {
      final DomHTMLInputElement element = domElement as DomHTMLInputElement;
      if (placeholder != null) {
        element.placeholder = placeholder;
      }
      if (autofillHint != null) {
        element.name = autofillHint;
        element.id = autofillHint;
        if (autofillHint.contains('password')) {
          element.type = 'password';
        } else {
          element.type = 'text';
        }
      }
      element.autocomplete = autofillHint ?? 'on';
    } else if (domInstanceOfString(domElement, 'HTMLTextAreaElement')) {
      final DomHTMLTextAreaElement element = domElement as DomHTMLTextAreaElement;
      if (placeholder != null) {
        element.placeholder = placeholder;
      }
      if (autofillHint != null) {
        element.name = autofillHint;
        element.id = autofillHint;
      }
      element.setAttribute('autocomplete', autofillHint ?? 'on');
    }
  }
}

/// Replaces a range of text in the original string with the text given in the
/// replacement string.
String _replace(String originalText, String replacementText, ui.TextRange replacedRange) {
  assert(replacedRange.isValid);
  assert(replacedRange.start <= originalText.length && replacedRange.end <= originalText.length);

  final ui.TextRange normalizedRange = ui.TextRange(start: math.min(replacedRange.start, replacedRange.end), end: math.max(replacedRange.start, replacedRange.end));

  return normalizedRange.textBefore(originalText) + replacementText + normalizedRange.textAfter(originalText);
}

/// The change between the last editing state and the current editing state
/// of a text field.
///
/// This is packaged into a JSON and sent to the framework
/// to be processed into a concrete [TextEditingDelta].
class TextEditingDeltaState {
  TextEditingDeltaState({
    this.oldText = '',
    this.deltaText = '',
    this.deltaStart = -1,
    this.deltaEnd = -1,
    this.baseOffset,
    this.extentOffset,
    this.composingOffset,
    this.composingExtent,
  });

  /// Infers the correct delta values based on information from the new editing state
  /// and the last editing state.
  ///
  /// For a deletion, the length and the direction of the deletion (backward or forward)
  /// are calculated by comparing the new and last editing states.
  /// If the deletion is backward, the length is susbtracted from the [deltaEnd]
  /// that we set when beforeinput was fired to determine the [deltaStart].
  /// If the deletion is forward, [deltaStart] is set to the new editing state baseOffset
  /// and [deltaEnd] is set to [deltaStart] incremented by the length of the deletion.
  ///
  /// For a replacement at a selection we set the [deltaStart] to be the beginning of the selection
  /// from the last editing state.
  ///
  /// For the composing region we check if a composing range was captured by the compositionupdate event,
  /// we have a non empty [deltaText], and that we did not have an active selection. An active selection
  /// would mean we are not composing.
  ///
  /// We then verify that the delta we collected results in the text contained within the new editing state
  /// when applied to the last editing state. If it is not then we use our new editing state as the source of truth,
  /// and use regex to find the correct [deltaStart] and [deltaEnd].
  static TextEditingDeltaState inferDeltaState(EditingState newEditingState, EditingState? lastEditingState, TextEditingDeltaState lastTextEditingDeltaState) {
    final TextEditingDeltaState newTextEditingDeltaState = lastTextEditingDeltaState.copyWith();
    final bool previousSelectionWasCollapsed = lastEditingState?.baseOffset == lastEditingState?.extentOffset;
    final bool isTextBeingRemoved = newTextEditingDeltaState.deltaText.isEmpty && newTextEditingDeltaState.deltaEnd != -1;
    final bool isTextBeingChangedAtActiveSelection = newTextEditingDeltaState.deltaText.isNotEmpty && !previousSelectionWasCollapsed;

    if (isTextBeingRemoved) {
      // When text is deleted outside of the composing region or is cut using the native toolbar,
      // we calculate the length of the deleted text by comparing the new and old editing state lengths.
      // If the deletion is backward, the length is susbtracted from the [deltaEnd]
      // that we set when beforeinput was fired to determine the [deltaStart].
      // If the deletion is forward, [deltaStart] is set to the new editing state baseOffset
      // and [deltaEnd] is set to [deltaStart] incremented by the length of the deletion.
      final int deletedLength = newTextEditingDeltaState.oldText.length - newEditingState.text!.length;
      final bool backwardDeletion = newEditingState.baseOffset != lastEditingState?.baseOffset;
      if (backwardDeletion) {
        newTextEditingDeltaState.deltaStart = newTextEditingDeltaState.deltaEnd - deletedLength;
      } else {
        // Forward deletion
        newTextEditingDeltaState.deltaStart = newEditingState.baseOffset!;
        newTextEditingDeltaState.deltaEnd = newTextEditingDeltaState.deltaStart + deletedLength;
      }
    } else if (isTextBeingChangedAtActiveSelection) {
      // When a selection of text is replaced by a copy/paste operation we set the starting range
      // of the delta to be the beginning of the selection of the previous editing state.
      newTextEditingDeltaState.deltaStart = lastEditingState!.baseOffset!;
    }

    // If we are composing then set the delta range to the composing region we
    // captured in compositionupdate.
    final bool isCurrentlyComposing = newTextEditingDeltaState.composingOffset != null && newTextEditingDeltaState.composingOffset != newTextEditingDeltaState.composingExtent;
    if (newTextEditingDeltaState.deltaText.isNotEmpty && previousSelectionWasCollapsed && isCurrentlyComposing) {
      newTextEditingDeltaState.deltaStart = newTextEditingDeltaState.composingOffset!;
    }

    final bool isDeltaRangeEmpty = newTextEditingDeltaState.deltaStart == -1 && newTextEditingDeltaState.deltaStart == newTextEditingDeltaState.deltaEnd;
    if (!isDeltaRangeEmpty) {
      // To verify the range of our delta we should compare the newEditingState's
      // text with the delta applied to the oldText. If they differ then capture
      // the correct delta range from the newEditingState's text value.
      //
      // We can assume the deltaText for additions and replacements to the text value
      // are accurate. What may not be accurate is the range of the delta.
      //
      // We can think of the newEditingState as our source of truth.
      //
      // This verification is needed for cases such as the insertion of a period
      // after a double space, and the insertion of an accented character through
      // a native composing menu.
      final ui.TextRange replacementRange = ui.TextRange(start: newTextEditingDeltaState.deltaStart, end: newTextEditingDeltaState.deltaEnd);
      final String textAfterDelta = _replace(
          newTextEditingDeltaState.oldText, newTextEditingDeltaState.deltaText,
          replacementRange);
      final bool isDeltaVerified = textAfterDelta == newEditingState.text!;

      if (!isDeltaVerified) {
        // 1. Find all matches for deltaText.
        // 2. Apply matches/replacement to oldText until oldText matches the
        // new editing state's text value.
        final bool isPeriodInsertion = newTextEditingDeltaState.deltaText.contains('.');
        final RegExp deltaTextPattern = RegExp(RegExp.escape(newTextEditingDeltaState.deltaText));
        for (final Match match in deltaTextPattern.allMatches(newEditingState.text!)) {
          String textAfterMatch;
          int actualEnd;
          final bool isMatchWithinOldTextBounds = match.start >= 0 && match.end <= newTextEditingDeltaState.oldText.length;
          if (!isMatchWithinOldTextBounds) {
            actualEnd = match.start + newTextEditingDeltaState.deltaText.length - 1;
            textAfterMatch = _replace(
              newTextEditingDeltaState.oldText,
              newTextEditingDeltaState.deltaText,
              ui.TextRange(
                start: match.start,
                end: actualEnd,
              ),
            );
          } else {
            actualEnd = actualEnd = isPeriodInsertion? match.end - 1 : match.end;
            textAfterMatch = _replace(
              newTextEditingDeltaState.oldText,
              newTextEditingDeltaState.deltaText,
              ui.TextRange(
                start: match.start,
                end: actualEnd,
              ),
            );
          }

          if (textAfterMatch == newEditingState.text!) {
            newTextEditingDeltaState.deltaStart = match.start;
            newTextEditingDeltaState.deltaEnd = actualEnd;
            break;
          }
        }
      }
    }

    // Update selection of the delta using information from the new editing state.
    newTextEditingDeltaState.baseOffset = newEditingState.baseOffset;
    newTextEditingDeltaState.extentOffset = newEditingState.extentOffset;

    return newTextEditingDeltaState;
  }

  /// The text before the text field was updated.
  String oldText;

  /// The text that is being inserted/replaced into the text field.
  /// This will be an empty string for deletions and non text updates
  /// such as selection updates.
  String deltaText;

  /// The position in the text field where the change begins.
  ///
  /// Has a default value of -1 to signify an empty range.
  int deltaStart;

  /// The position in the text field where the change ends.
  ///
  /// Has a default value of -1 to signify an empty range.
  int deltaEnd;

  /// The updated starting position of the selection in the text field.
  int? baseOffset;

  /// The updated terminating position of the selection in the text field.
  int? extentOffset;

  /// The starting position of the composing region.
  int? composingOffset;

  /// The terminating position of the composing region.
  int? composingExtent;

  Map<String, dynamic> toFlutter() => <String, dynamic>{
    'deltas': <Map<String, dynamic>>[
      <String, dynamic>{
        'oldText': oldText,
        'deltaText': deltaText,
        'deltaStart': deltaStart,
        'deltaEnd': deltaEnd,
        'selectionBase': baseOffset,
        'selectionExtent': extentOffset,
        'composingBase': composingOffset,
        'composingExtent': composingExtent
      },
    ],
  };

  TextEditingDeltaState copyWith({
    String? oldText,
    String? deltaText,
    int? deltaStart,
    int? deltaEnd,
    int? baseOffset,
    int? extentOffset,
    int? composingOffset,
    int? composingExtent,
  }) {
    return TextEditingDeltaState(
      oldText: oldText ?? this.oldText,
      deltaText: deltaText ?? this.deltaText,
      deltaStart: deltaStart ?? this.deltaStart,
      deltaEnd: deltaEnd ?? this.deltaEnd,
      baseOffset: baseOffset ?? this.baseOffset,
      extentOffset: extentOffset ?? this.extentOffset,
      composingOffset: composingOffset ?? this.composingOffset,
      composingExtent: composingExtent ?? this.composingExtent,
    );
  }
}

/// The current text and selection state of a text field.
class EditingState {
  EditingState({
      this.text,
      int? baseOffset,
      int? extentOffset,
      this.composingBaseOffset = -1,
      this.composingExtentOffset = -1
    }) :
        // Don't allow negative numbers.
        baseOffset = math.max(0, baseOffset ?? 0),
        // Don't allow negative numbers.
        extentOffset = math.max(0, extentOffset ?? 0);

  /// Creates an [EditingState] instance using values from an editing state Map
  /// coming from Flutter.
  ///
  /// The `editingState` Map has the following structure:
  /// ```json
  /// {
  ///   "text": "The text here",
  ///   "selectionBase": 0,
  ///   "selectionExtent": 0,
  ///   "selectionAffinity": "TextAffinity.upstream",
  ///   "selectionIsDirectional": false,
  ///   "composingBase": -1,
  ///   "composingExtent": -1
  /// }
  /// ```
  ///
  /// Flutter Framework can send the [selectionBase] and [selectionExtent] as
  /// -1, if so 0 assigned to the [baseOffset] and [extentOffset]. -1 is not a
  /// valid selection range for input DOM elements.
  factory EditingState.fromFrameworkMessage(
      Map<String, dynamic> flutterEditingState) {
    final String? text = flutterEditingState.tryString('text');

    final int selectionBase = flutterEditingState.readInt('selectionBase');
    final int selectionExtent = flutterEditingState.readInt('selectionExtent');

    final int? composingBase = flutterEditingState.tryInt('composingBase');
    final int? composingExtent = flutterEditingState.tryInt('composingExtent');

    return EditingState(
      text: text,
      baseOffset: selectionBase,
      extentOffset: selectionExtent,
      composingBaseOffset: composingBase ?? -1,
      composingExtentOffset: composingExtent ?? -1
    );
  }

  /// Creates an [EditingState] instance using values from the editing element
  /// in the DOM.
  ///
  /// [domElement] can be a [InputElement] or a [TextAreaElement] depending on
  /// the [InputType] of the text field.
  factory EditingState.fromDomElement(DomHTMLElement? domElement) {
    if (domInstanceOfString(domElement, 'HTMLInputElement')) {
      final DomHTMLInputElement element = domElement! as DomHTMLInputElement;
      return EditingState(
          text: element.value,
          baseOffset: element.selectionStart?.toInt(),
          extentOffset: element.selectionEnd?.toInt());
    } else if (domInstanceOfString(domElement, 'HTMLTextAreaElement')) {
      final DomHTMLTextAreaElement element = domElement! as
          DomHTMLTextAreaElement;
      return EditingState(
          text: element.value,
          baseOffset: element.selectionStart?.toInt(),
          extentOffset: element.selectionEnd?.toInt());
    } else {
      throw UnsupportedError('Initialized with unsupported input type');
    }
  }

  // Pick the smallest selection index for base.
  int get minOffset => math.min(baseOffset ?? 0, extentOffset ?? 0);
  // Pick the greatest selection index for extent.
  int get maxOffset => math.max(baseOffset ?? 0, extentOffset ?? 0);

    EditingState copyWith({
     String? text,
     int? baseOffset,
     int? extentOffset,
     int? composingBaseOffset,
     int? composingExtentOffset,
   }) {
     return EditingState(
       text: text ?? this.text,
       baseOffset: baseOffset ?? this.baseOffset,
       extentOffset: extentOffset ?? this.extentOffset,
       composingBaseOffset: composingBaseOffset ?? this.composingBaseOffset,
       composingExtentOffset: composingExtentOffset ?? this.composingExtentOffset,
     );
   }

  /// The counterpart of [EditingState.fromFrameworkMessage]. It generates a Map that
  /// can be sent to Flutter.
  // TODO(mdebbar): Should we get `selectionAffinity` and other properties from flutter's editing state?
  Map<String, dynamic> toFlutter() => <String, dynamic>{
        'text': text,
        'selectionBase': baseOffset,
        'selectionExtent': extentOffset,
        'composingBase': composingBaseOffset,
        'composingExtent': composingExtentOffset,
      };

  /// The current text being edited.
  final String? text;

  /// The offset at which the text selection originates.
  final int? baseOffset;

  /// The offset at which the text selection terminates.
  final int? extentOffset;

  /// The offset at which [CompositionAwareMixin.composingText] begins, if any.
  final int composingBaseOffset;

  /// The offset at which [CompositionAwareMixin.composingText] terminates, if any.
  final int composingExtentOffset;

  /// Whether the current editing state is valid or not.
  bool get isValid => baseOffset! >= 0 && extentOffset! >= 0;

  @override
  int get hashCode => Object.hash(
    text, baseOffset, extentOffset, composingBaseOffset, composingExtentOffset
  );

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (runtimeType != other.runtimeType) {
      return false;
    }
    return other is EditingState &&
        other.text == text &&
        other.minOffset == minOffset &&
        other.maxOffset == maxOffset &&
        other.composingBaseOffset == composingBaseOffset &&
        other.composingExtentOffset == composingExtentOffset;
  }

  @override
  String toString() {
    return assertionsEnabled
        ? 'EditingState("$text", base:$baseOffset, extent:$extentOffset, composingBase:$composingBaseOffset, composingExtent:$composingExtentOffset)'
        : super.toString();
  }

  /// Sets the selection values of a DOM element using this [EditingState].
  ///
  /// [domElement] can be a [InputElement] or a [TextAreaElement] depending on
  /// the [InputType] of the text field.
  ///
  /// This should only be used by focused elements only, because only focused
  /// elements can have their text selection range set. Attempting to set
  /// selection range on a non-focused element will cause it to request focus.
  ///
  /// See also:
  ///
  ///  * [applyTextToDomElement], which is used for non-focused elements.
  void applyToDomElement(DomHTMLElement? domElement) {
    if (domInstanceOfString(domElement, 'HTMLInputElement')) {
      final DomHTMLInputElement element = domElement! as DomHTMLInputElement;
      element.value = text;
      element.setSelectionRange(minOffset, maxOffset);
    } else if (domInstanceOfString(domElement, 'HTMLTextAreaElement')) {
      final DomHTMLTextAreaElement element = domElement! as
          DomHTMLTextAreaElement;
      element.value = text;
      element.setSelectionRange(minOffset, maxOffset);
    } else {
      throw UnsupportedError('Unsupported DOM element type: <${domElement?.tagName}> (${domElement.runtimeType})');
    }
  }

  /// Applies the [text] to the [domElement].
  ///
  /// This is used by non-focused elements.
  ///
  /// See also:
  ///
  ///  * [applyToDomElement], which is used for focused elements.
  void applyTextToDomElement(DomHTMLElement? domElement) {
    if (domInstanceOfString(domElement, 'HTMLInputElement')) {
      final DomHTMLInputElement element = domElement! as DomHTMLInputElement;
      element.value = text;
    } else if (domInstanceOfString(domElement, 'HTMLTextAreaElement')) {
      final DomHTMLTextAreaElement element = domElement! as
          DomHTMLTextAreaElement;
      element.value = text;
    } else {
      throw UnsupportedError('Unsupported DOM element type');
    }
  }
}

/// Controls the appearance of the input control being edited.
///
/// For example, [inputType] determines whether we should use `<input>` or
/// `<textarea>` as a backing DOM element.
///
/// This corresponds to Flutter's [TextInputConfiguration].
class InputConfiguration {
  InputConfiguration({
    this.inputType = EngineInputType.text,
    this.inputAction = 'TextInputAction.done',
    this.obscureText = false,
    this.readOnly = false,
    this.autocorrect = true,
    this.textCapitalization =
        const TextCapitalizationConfig.defaultCapitalization(),
    this.autofill,
    this.autofillGroup,
    this.enableDeltaModel = false,
  });

  InputConfiguration.fromFrameworkMessage(
      Map<String, dynamic> flutterInputConfiguration)
      : inputType = EngineInputType.fromName(
          flutterInputConfiguration.readJson('inputType').readString('name'),
          isDecimal: flutterInputConfiguration.readJson('inputType').tryBool('decimal') ?? false,
        ),
        inputAction =
            flutterInputConfiguration.tryString('inputAction') ?? 'TextInputAction.done',
        obscureText = flutterInputConfiguration.tryBool('obscureText') ?? false,
        readOnly = flutterInputConfiguration.tryBool('readOnly') ?? false,
        autocorrect = flutterInputConfiguration.tryBool('autocorrect') ?? true,
        textCapitalization = TextCapitalizationConfig.fromInputConfiguration(
          flutterInputConfiguration.readString('textCapitalization'),
        ),
        autofill = flutterInputConfiguration.containsKey('autofill')
            ? AutofillInfo.fromFrameworkMessage(
                flutterInputConfiguration.readJson('autofill'))
            : null,
        autofillGroup = EngineAutofillForm.fromFrameworkMessage(
          flutterInputConfiguration.tryJson('autofill'),
          flutterInputConfiguration.tryList('fields'),
        ),
        enableDeltaModel = flutterInputConfiguration.tryBool('enableDeltaModel') ?? false;

  /// The type of information being edited in the input control.
  final EngineInputType inputType;

  /// The default action for the input field.
  final String inputAction;

  /// Whether the text field can be edited or not.
  ///
  /// Defaults to false.
  final bool readOnly;

  /// Whether to hide the text being edited.
  final bool obscureText;

  /// Whether to enable autocorrection.
  ///
  /// Definition of autocorrect can be found in:
  /// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
  ///
  /// For future manual tests, note that autocorrect is an attribute only
  /// supported by Safari.
  final bool autocorrect;

  final bool enableDeltaModel;

  final AutofillInfo? autofill;

  final EngineAutofillForm? autofillGroup;

  final TextCapitalizationConfig textCapitalization;
}

typedef OnChangeCallback = void Function(EditingState? editingState, TextEditingDeltaState? editingDeltaState);
typedef OnActionCallback = void Function(String? inputAction);

/// Provides HTML DOM functionality for editable text.
///
/// A concrete implementation is picked at runtime based on the current
/// operating system, web browser, and accessibility mode.
abstract class TextEditingStrategy {
  void initializeTextEditing(
    InputConfiguration inputConfig, {
    required OnChangeCallback onChange,
    required OnActionCallback onAction,
  });

  /// Sets the initial placement of the DOM element on the UI.
  ///
  /// The element must be located exactly in the same place with the editable
  /// widget. However, its contents and cursor will be invisible.
  ///
  /// Users can interact with the element and use the functionality of the
  /// right-click menu, such as copy, paste, cut, select, translate, etc.
  void initializeElementPlacement();

  /// Register event listeners to the DOM element.
  ///
  /// These event listener will be removed in [disable].
  void addEventHandlers();

  /// Update the element's position.
  ///
  /// The position will be updated everytime Flutter Framework sends
  /// 'TextInput.setEditableSizeAndTransform' message.
  void updateElementPlacement(EditableTextGeometry geometry);

  /// Set editing state of the element.
  ///
  /// This includes text and selection relelated states. The editing state will
  /// be updated everytime Flutter Framework sends 'TextInput.setEditingState'
  /// message.
  void setEditingState(EditingState editingState);

  /// Set style to the native DOM element used for text editing.
  void updateElementStyle(EditableTextStyle style);

  /// Disables the element so it's no longer used for text editing.
  ///
  /// Calling [disable] also removes any registered event listeners.
  void disable();
}

/// A [TextEditingStrategy] that places its [domElement] assuming no
/// prior transform or sizing is applied to it.
///
/// This implementation is used by text editables when semantics is not
/// enabled. With semantics enabled the placement is provided by the semantics
/// tree.
class GloballyPositionedTextEditingStrategy extends DefaultTextEditingStrategy {
  GloballyPositionedTextEditingStrategy(super.owner);

  @override
  void placeElement() {
    geometry?.applyToDomElement(activeDomElement);
    if (hasAutofillGroup) {
      placeForm();
      // Set the last editing state if it exists, this is critical for a
      // users ongoing work to continue uninterrupted when there is an update to
      // the transform.
      lastEditingState?.applyToDomElement(domElement);
      // On Chrome, when a form is focused, it opens an autofill menu
      // immediately.
      // Flutter framework sends `setEditableSizeAndTransform` for informing
      // the engine about the location of the text field. This call will
      // arrive after `show` call.
      // Therefore on Chrome we place the element when
      //  `setEditableSizeAndTransform` method is called and focus on the form
      // only after placing it to the correct position. Hence autofill menu
      // does not appear on top-left of the page.
      // Refocus on the elements after applying the geometry.
      focusedFormElement!.focus();
      activeDomElement.focus();
    }
  }
}

/// A [TextEditingStrategy] for Safari Desktop Browser.
///
/// It places its [domElement] assuming no prior transform or sizing is applied
/// to it.
///
/// In case of an autofill enabled form, it does not append the form element
/// to the DOM, until the geometry information is updated.
///
/// This implementation is used by text editables when semantics is not
/// enabled. With semantics enabled the placement is provided by the semantics
/// tree.
class SafariDesktopTextEditingStrategy extends DefaultTextEditingStrategy {
  SafariDesktopTextEditingStrategy(super.owner);

  /// Appending an element on the DOM for Safari Desktop Browser.
  ///
  /// This method is only called when geometry information is updated by
  /// 'TextInput.setEditableSizeAndTransform' message.
  ///
  /// This method is similar to the [GloballyPositionedTextEditingStrategy].
  /// The only part different: this method does not call `super.placeElement()`,
  /// which in current state calls `domElement.focus()`.
  ///
  /// Making an extra `focus` request causes flickering in Safari.
  @override
  void placeElement() {
    geometry?.applyToDomElement(activeDomElement);
    if (hasAutofillGroup) {
      placeForm();
      // On Safari Desktop, when a form is focused, it opens an autofill menu
      // immediately.
      // Flutter framework sends `setEditableSizeAndTransform` for informing
      // the engine about the location of the text field. This call may arrive
      // after the first `show` call, depending on the text input widget's
      // implementation. Therefore form is placed, when
      // `setEditableSizeAndTransform` method is called and focus called on the
      // form only after placing it to the correct position and only once after
      // that. Calling focus multiple times causes flickering.
      focusedFormElement!.focus();

      // Set the last editing state if it exists, this is critical for a
      // users ongoing work to continue uninterrupted when there is an update to
      // the transform.
      // If domElement is not focused cursor location will not be correct.
      activeDomElement.focus();
      lastEditingState?.applyToDomElement(activeDomElement);
    }
  }

  @override
  void initializeElementPlacement() {
    if (geometry != null) {
      placeElement();
    }
    activeDomElement.focus();
  }
}

/// Class implementing the default editing strategies for text editing.
///
/// This class uses a DOM element to provide text editing capabilities.
///
/// The backing DOM element could be one of:
///
/// 1. `<input>`.
/// 2. `<textarea>`.
/// 3. `<span contenteditable="true">`.
///
/// This class includes all the default behaviour for an editing element as
/// well as the common properties such as [domElement].
///
/// Strategies written for different form factors and browsers should extend
/// this class instead of extending the interface [TextEditingStrategy]. In
/// particular, a concrete implementation is expected to override
/// [placeElement] that places the DOM element accordingly. The default
/// implementation of [placeElement] does not position the element.
///
/// Unless a formfactor/browser requires specific implementation for a specific
/// strategy the methods in this class should be used.
abstract class DefaultTextEditingStrategy with CompositionAwareMixin implements TextEditingStrategy  {
  DefaultTextEditingStrategy(this.owner);

  final HybridTextEditing owner;

  bool isEnabled = false;

  /// The DOM element used for editing, if any.
  DomHTMLElement? domElement;

  /// Same as [domElement] but null-checked.
  ///
  /// This must only be called in places that know for sure that a DOM element
  /// is currently available for editing.
  DomHTMLElement get activeDomElement {
    assert(
      domElement != null,
      'The DOM element of this text editing strategy is not currently active.',
    );
    return domElement!;
  }

  late InputConfiguration inputConfiguration;
  EditingState? lastEditingState;

  TextEditingDeltaState? _editingDeltaState;
  TextEditingDeltaState get editingDeltaState {
    _editingDeltaState ??= TextEditingDeltaState(oldText: lastEditingState!.text!);
    return _editingDeltaState!;
  }

  /// Styles associated with the editable text.
  EditableTextStyle? style;

  /// Size and transform of the editable text on the page.
  EditableTextGeometry? geometry;

  OnChangeCallback? onChange;
  OnActionCallback? onAction;

  final List<DomSubscription> subscriptions = <DomSubscription>[];

  bool get hasAutofillGroup => inputConfiguration.autofillGroup != null;

  /// Whether the focused input element is part of a form.
  bool get appendedToForm => _appendedToForm;
  bool _appendedToForm = false;

  DomHTMLFormElement? get focusedFormElement =>
      inputConfiguration.autofillGroup?.formElement;

  @override
  void initializeTextEditing(
    InputConfiguration inputConfig, {
    required OnChangeCallback onChange,
    required OnActionCallback onAction,
  }) {
    assert(!isEnabled);

    domElement = inputConfig.inputType.createDomElement();
    applyConfiguration(inputConfig);

    _setStaticStyleAttributes(activeDomElement);
    style?.applyToDomElement(activeDomElement);

    if (!hasAutofillGroup) {
      // If there is an Autofill Group the `FormElement`, it will be appended to the
      // DOM later, when the first location information arrived.
      // Otherwise, on Blink based Desktop browsers, the autofill menu appears
      // on top left of the screen.
      defaultTextEditingRoot.append(activeDomElement);
      _appendedToForm = false;
    }

    initializeElementPlacement();

    isEnabled = true;
    this.onChange = onChange;
    this.onAction = onAction;
  }

  void applyConfiguration(InputConfiguration config) {
    inputConfiguration = config;

    if (config.readOnly) {
      activeDomElement.setAttribute('readonly', 'readonly');
    } else {
      activeDomElement.removeAttribute('readonly');
    }

    if (config.obscureText) {
      activeDomElement.setAttribute('type', 'password');
    }

    if (config.inputType == EngineInputType.none) {
      activeDomElement.setAttribute('inputmode', 'none');
    }

    final EngineInputAction action = EngineInputAction.fromName(config.inputAction);
    action.configureInputAction(activeDomElement);

    final AutofillInfo? autofill = config.autofill;
    if (autofill != null) {
      autofill.applyToDomElement(activeDomElement, focusedElement: true);
    } else {
      activeDomElement.setAttribute('autocomplete', 'off');
    }

    final String autocorrectValue = config.autocorrect ? 'on' : 'off';
    activeDomElement.setAttribute('autocorrect', autocorrectValue);
  }

  @override
  void initializeElementPlacement() {
    placeElement();
  }

  @override
  void addEventHandlers() {
    if (inputConfiguration.autofillGroup != null) {
      subscriptions
          .addAll(inputConfiguration.autofillGroup!.addInputEventListeners());
    }

    // Subscribe to text and selection changes.
    subscriptions.add(DomSubscription(activeDomElement, 'input',
            allowInterop(handleChange)));

    subscriptions.add(DomSubscription(activeDomElement, 'keydown',
            allowInterop(maybeSendAction)));

    subscriptions.add(DomSubscription(domDocument, 'selectionchange',
            allowInterop(handleChange)));

    activeDomElement.addEventListener('beforeinput',
        allowInterop(handleBeforeInput));

    addCompositionEventHandlers(activeDomElement);

    // Refocus on the activeDomElement after blur, so that user can keep editing the
    // text field.
    subscriptions.add(DomSubscription(activeDomElement, 'blur',
            allowInterop((_) { activeDomElement.focus(); })));

    preventDefaultForMouseEvents();
  }

  @override
  void updateElementPlacement(EditableTextGeometry textGeometry) {
    geometry = textGeometry;
    if (isEnabled) {
      placeElement();
    }
  }

  @override
  void updateElementStyle(EditableTextStyle textStyle) {
    style = textStyle;
    if (isEnabled) {
      textStyle.applyToDomElement(activeDomElement);
    }
  }

  @override
  void disable() {
    assert(isEnabled);

    isEnabled = false;
    lastEditingState = null;
    _editingDeltaState = null;
    style = null;
    geometry = null;

    for (int i = 0; i < subscriptions.length; i++) {
      subscriptions[i].cancel();
    }
    subscriptions.clear();
    removeCompositionEventHandlers(activeDomElement);

    // If focused element is a part of a form, it needs to stay on the DOM
    // until the autofill context of the form is finalized.
    // More details on `TextInput.finishAutofillContext` call.
    if (_appendedToForm &&
        inputConfiguration.autofillGroup?.formElement != null) {
      // Subscriptions are removed, listeners won't be triggered.
      activeDomElement.blur();
      _hideAutofillElements(activeDomElement, isOffScreen: true);
      inputConfiguration.autofillGroup?.storeForm();
    } else {
      activeDomElement.remove();
    }
    domElement = null;
  }

  @override
  void setEditingState(EditingState? editingState) {
    lastEditingState = editingState;
    if (!isEnabled || !editingState!.isValid) {
      return;
    }
    lastEditingState!.applyToDomElement(domElement);
  }

  void placeElement() {
    activeDomElement.focus();
  }

  void placeForm() {
    inputConfiguration.autofillGroup!.placeForm(activeDomElement);
    _appendedToForm = true;
  }

  void handleChange(DomEvent event) {
    assert(isEnabled);

    EditingState newEditingState = EditingState.fromDomElement(activeDomElement);
    newEditingState = determineCompositionState(newEditingState);

    TextEditingDeltaState? newTextEditingDeltaState;
    if (inputConfiguration.enableDeltaModel) {
      editingDeltaState.composingOffset = newEditingState.composingBaseOffset;
      editingDeltaState.composingExtent = newEditingState.composingExtentOffset;
      newTextEditingDeltaState = TextEditingDeltaState.inferDeltaState(newEditingState, lastEditingState, editingDeltaState);
    }

    if (newEditingState != lastEditingState) {
      lastEditingState = newEditingState;
      _editingDeltaState = newTextEditingDeltaState;
      onChange!(lastEditingState, _editingDeltaState);
      // Flush delta after it has been sent to framework.
      _editingDeltaState = null;
    }
  }

  void handleBeforeInput(DomEvent event) {
    // In some cases the beforeinput event is not fired such as when the selection
    // of a text field is updated. In this case only the oninput event is fired.
    // We still want a delta generated in these cases so we can properly update
    // the selection. We begin to set the deltaStart and deltaEnd in beforeinput
    // because a change in the selection will not have a delta range, it will only
    // have a baseOffset and extentOffset. If these are set inside of inferDeltaState
    // then the method will incorrectly report a deltaStart and deltaEnd for a non
    // text update delta.
    final String? eventData = getJsProperty<void>(event, 'data') as String?;
    final String? inputType = getJsProperty<void>(event, 'inputType') as String?;

    if (inputType != null) {
      if (inputType.contains('delete')) {
        // The deltaStart is set in handleChange because there is where we get access
        // to the new selection baseOffset which is our new deltaStart.
        editingDeltaState.deltaText = '';
        editingDeltaState.deltaEnd = lastEditingState!.extentOffset!;
      } else if (inputType == 'insertLineBreak'){
        // event.data is null on a line break, so we manually set deltaText as a line break by setting it to '\n'.
        editingDeltaState.deltaText = '\n';
        editingDeltaState.deltaStart = lastEditingState!.extentOffset!;
        editingDeltaState.deltaEnd = lastEditingState!.extentOffset!;
      } else if (eventData != null) {
        // When event.data is not null we will begin by considering this delta as an insertion
        // at the selection extentOffset. This may change due to logic in handleChange to handle
        // composition and other IME behaviors.
        editingDeltaState.deltaText = eventData;
        editingDeltaState.deltaStart = lastEditingState!.extentOffset!;
        editingDeltaState.deltaEnd = lastEditingState!.extentOffset!;
      }
    }
  }

  void maybeSendAction(DomEvent e) {
    if (domInstanceOfString(e, 'KeyboardEvent')) {
      final DomKeyboardEvent event = e as DomKeyboardEvent;
      if (event.keyCode == _kReturnKeyCode) {
        onAction!(inputConfiguration.inputAction);
        // Prevent the browser from inserting a new line when it's not a multiline input.
        if (inputConfiguration.inputType is! MultilineInputType) {
          event.preventDefault();
        }
      }
    }
  }

  /// Enables the element so it can be used to edit text.
  ///
  /// Register [callback] so that it gets invoked whenever any change occurs in
  /// the text editing element.
  ///
  /// Changes could be:
  /// - Text changes, or
  /// - Selection changes.
  void enable(
    InputConfiguration inputConfig, {
    required OnChangeCallback onChange,
    required OnActionCallback onAction,
  }) {
    assert(!isEnabled);

    initializeTextEditing(inputConfig, onChange: onChange, onAction: onAction);

    addEventHandlers();

    if (lastEditingState != null) {
      setEditingState(lastEditingState);
    }

    // Re-focuses after setting editing state.
    activeDomElement.focus();
  }

  /// Prevent default behavior for mouse down, up and move.
  ///
  /// When normal mouse events are not prevented, in desktop browsers, mouse
  /// selection conflicts with selection sent from the framework, which creates
  /// flickering during selection by mouse.
  void preventDefaultForMouseEvents() {
    subscriptions.add(
        DomSubscription(activeDomElement, 'mousedown', allowInterop((_) {
      _.preventDefault();
    })));

    subscriptions.add(
        DomSubscription(activeDomElement, 'mouseup', allowInterop((_) {
      _.preventDefault();
    })));

    subscriptions.add(
        DomSubscription(activeDomElement, 'mousemove', allowInterop((_) {
      _.preventDefault();
    })));
  }
}

/// IOS/Safari behaviour for text editing.
///
/// In iOS, the virtual keyboard might shifts the screen up to make input
/// visible depending on the location of the focused input element.
///
/// Due to this [initializeElementPlacement] and [updateElementPlacement]
/// strategies are different.
///
/// [disable] is also different since the [_positionInputElementTimer]
/// also needs to be cleaned.
///
/// inputmodeAttribute needs to be set for mobile devices. Due to this
/// [initializeTextEditing] is different.
class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
  IOSTextEditingStrategy(super.owner);

  /// Timer that times when to set the location of the input text.
  ///
  /// This is only used for iOS. In iOS, virtual keyboard shifts the screen.
  /// There is no callback to know if the keyboard is up and how much the screen
  /// has shifted. Therefore instead of listening to the shift and passing this
  /// information to Flutter Framework, we are trying to stop the shift.
  ///
  /// In iOS, the virtual keyboard shifts the screen up if the focused input
  /// element is under the keyboard or very close to the keyboard. Before the
  /// focus is called we are positioning it offscreen. The location of the input
  /// in iOS is set to correct place, 100ms after focus. We use this timer for
  /// timing this delay.
  Timer? _positionInputElementTimer;
  static const Duration _delayBeforePlacement = Duration(milliseconds: 100);

  /// This interval between the blur subscription and callback is considered to
  /// be fast.
  ///
  /// This is only used for iOS. The blur callback may trigger as soon as the
  /// creation of the subscription. Occasionally in this case, the virtual
  /// keyboard will quickly show and hide again.
  ///
  /// Less than this interval allows the virtual keyboard to keep showing up
  /// instead of hiding rapidly.
  static const Duration _blurFastCallbackInterval = Duration(milliseconds: 200);

  /// Whether or not the input element can be positioned at this point in time.
  ///
  /// This is currently only used in iOS. It's set to false before focusing the
  /// input field, and set back to true after a short timer. We do this because
  /// if the input field is positioned before focus, it could be pushed to an
  /// incorrect position by the virtual keyboard.
  ///
  /// See:
  ///
  /// * [_delayBeforePlacement] which controls how long to wait before
  ///   positioning the input field.
  bool _canPosition = true;

  @override
  void initializeTextEditing(
    InputConfiguration inputConfig, {
    required OnChangeCallback onChange,
    required OnActionCallback onAction,
  }) {
    super.initializeTextEditing(inputConfig,
        onChange: onChange, onAction: onAction);
    inputConfig.inputType.configureInputMode(activeDomElement);
    if (hasAutofillGroup) {
      placeForm();
    }
    inputConfig.textCapitalization.setAutocapitalizeAttribute(activeDomElement);
  }

  @override
  void initializeElementPlacement() {
    /// Position the element outside of the page before focusing on it. This is
    /// useful for not triggering a scroll when iOS virtual keyboard is
    /// coming up.
    activeDomElement.style.transform = 'translate(${offScreenOffset}px, ${offScreenOffset}px)';

    _canPosition = false;
  }

  @override
  void addEventHandlers() {
    if (inputConfiguration.autofillGroup != null) {
      subscriptions
          .addAll(inputConfiguration.autofillGroup!.addInputEventListeners());
    }

    // Subscribe to text and selection changes.
    subscriptions.add(DomSubscription(activeDomElement, 'input',
            allowInterop(handleChange)));

    subscriptions.add(DomSubscription(activeDomElement, 'keydown',
            allowInterop(maybeSendAction)));

    subscriptions.add(DomSubscription(domDocument, 'selectionchange',
            allowInterop(handleChange)));

    activeDomElement.addEventListener('beforeinput',
        allowInterop(handleBeforeInput));

    addCompositionEventHandlers(activeDomElement);

    // Position the DOM element after it is focused.
    subscriptions.add(DomSubscription(activeDomElement, 'focus',
            allowInterop((_) {
              // Cancel previous timer if exists.
              _schedulePlacement();
            })));

    _addTapListener();

    // Record start time of blur subscription.
    final Stopwatch blurWatch = Stopwatch()..start();

    // On iOS, blur is trigerred in the following cases:
    //
    // 1. The browser app is sent to the background (or the tab is changed). In
    //    this case, the window loses focus (see [windowHasFocus]),
    //    so we close the input connection with the framework.
    // 2. The user taps on another focusable element. In this case, we refocus
    //    the input field and wait for the framework to manage the focus change.
    // 3. The virtual keyboard is closed by tapping "done". We can't detect this
    //    programmatically, so we end up refocusing the input field. This is
    //    okay because the virtual keyboard will hide, and as soon as the user
    //    taps the text field again, the virtual keyboard will come up.
    // 4. Safari sometimes sends a blur event immediately after activating the
    //    input field. In this case, we want to keep the focus on the input field.
    //    In order to detect this, we measure how much time has passed since the
    //    input field was activated. If the time is too short, we re-focus the
    //    input element.
    subscriptions.add(DomSubscription(activeDomElement, 'blur',
            allowInterop((_) {
              final bool isFastCallback = blurWatch.elapsed < _blurFastCallbackInterval;
              if (windowHasFocus && isFastCallback) {
                activeDomElement.focus();
              } else {
                owner.sendTextConnectionClosedToFrameworkIfAny();
              }
            })));
  }

  @override
  void updateElementPlacement(EditableTextGeometry textGeometry) {
    geometry = textGeometry;
    if (isEnabled && _canPosition) {
      placeElement();
    }
  }

  @override
  void disable() {
    super.disable();
    _positionInputElementTimer?.cancel();
    _positionInputElementTimer = null;
  }

  /// On iOS long press works differently than a single tap.
  ///
  /// On a normal tap the virtual keyboard comes up and users can enter text
  /// using the keyboard.
  ///
  /// The long press on the other hand focuses on the element without bringing
  /// up the virtual keyboard. It allows the users to modify the field by using
  /// copy/cut/select/paste etc.
  ///
  /// After a long press [domElement] is positioned to the correct place. If the
  /// user later single-tap on the [domElement] the virtual keyboard will come
  /// and might shift the page up.
  ///
  /// In order to prevent this shift, on a `click` event the position of the
  /// element is again set somewhere outside of the page and
  /// [_positionInputElementTimer] timer is restarted. The element will be
  /// placed to its correct position after [_delayBeforePlacement].
  void _addTapListener() {
    subscriptions.add(DomSubscription(activeDomElement, 'click', allowInterop((_) {
      // Check if the element is already positioned. If not this does not fall
      // under `The user was using the long press, now they want to enter text
      // via keyboard` journey.
      if (_canPosition) {
        // Re-place the element somewhere outside of the screen.
        initializeElementPlacement();

        // Re-configure the timer to place the element.
        _schedulePlacement();
      }
    })));
  }

  void _schedulePlacement() {
    _positionInputElementTimer?.cancel();
    _positionInputElementTimer = Timer(_delayBeforePlacement, () {
      _canPosition = true;
      placeElement();
    });
  }

  @override
  void placeElement() {
    activeDomElement.focus();
    geometry?.applyToDomElement(activeDomElement);
  }
}

/// Android behaviour for text editing.
///
/// inputmodeAttribute needs to be set for mobile devices. Due to this
/// [initializeTextEditing] is different.
///
/// Keyboard acts differently than other devices. [addEventHandlers] handles
/// this case as an extra.
class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
  AndroidTextEditingStrategy(super.owner);

  @override
  void initializeTextEditing(
    InputConfiguration inputConfig, {
    required OnChangeCallback onChange,
    required OnActionCallback onAction,
  }) {
    super.initializeTextEditing(inputConfig,
        onChange: onChange, onAction: onAction);
    inputConfig.inputType.configureInputMode(activeDomElement);
    if (hasAutofillGroup) {
      placeForm();
    } else {
      defaultTextEditingRoot.append(activeDomElement);
    }
    inputConfig.textCapitalization.setAutocapitalizeAttribute(
        activeDomElement);
  }

  @override
  void addEventHandlers() {
    if (inputConfiguration.autofillGroup != null) {
      subscriptions
          .addAll(inputConfiguration.autofillGroup!.addInputEventListeners());
    }

    // Subscribe to text and selection changes.
    subscriptions.add(
        DomSubscription(activeDomElement, 'input', allowInterop(handleChange)));

    subscriptions.add(
        DomSubscription(activeDomElement, 'keydown',
            allowInterop(maybeSendAction)));

    subscriptions.add(
        DomSubscription(domDocument, 'selectionchange',
            allowInterop(handleChange)));

    activeDomElement.addEventListener('beforeinput',
        allowInterop(handleBeforeInput));

    addCompositionEventHandlers(activeDomElement);

    subscriptions.add(
        DomSubscription(activeDomElement, 'blur',
            allowInterop((_) {
              if (windowHasFocus) {
                // Chrome on Android will hide the onscreen keyboard when you tap outside
                // the text box. Instead, we want the framework to tell us to hide the
                // keyboard via `TextInput.clearClient` or `TextInput.hide`. Therefore
                // refocus as long as [windowHasFocus] is true.
                activeDomElement.focus();
              } else {
                owner.sendTextConnectionClosedToFrameworkIfAny();
              }
            })));
  }

  @override
  void placeElement() {
    activeDomElement.focus();
    geometry?.applyToDomElement(activeDomElement);
  }
}

/// Firefox behaviour for text editing.
///
/// Selections are different in Firefox. [addEventHandlers] strategy is
/// impelemented diefferently in Firefox.
class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
  FirefoxTextEditingStrategy(super.owner);

  @override
  void initializeTextEditing(
    InputConfiguration inputConfig, {
    required OnChangeCallback onChange,
    required OnActionCallback onAction,
  }) {
    super.initializeTextEditing(inputConfig,
        onChange: onChange, onAction: onAction);
    if (hasAutofillGroup) {
      placeForm();
    }
  }

  @override
  void addEventHandlers() {
    if (inputConfiguration.autofillGroup != null) {
      subscriptions
          .addAll(inputConfiguration.autofillGroup!.addInputEventListeners());
    }

    // Subscribe to text and selection changes.
    subscriptions.add(
        DomSubscription(activeDomElement, 'input', allowInterop(handleChange)));

    subscriptions.add(
        DomSubscription(
            activeDomElement, 'keydown', allowInterop(maybeSendAction)));

    activeDomElement.addEventListener('beforeinput',
        allowInterop(handleBeforeInput));

    addCompositionEventHandlers(activeDomElement);

    // Detects changes in text selection.
    //
    // In Firefox, when cursor moves, neither selectionChange nor onInput
    // events are triggered. We are listening to keyup event. Selection start,
    // end values are used to decide if the text cursor moved.
    //
    // Specific keycodes are not checked since users/applications can bind
    // their own keys to move the text cursor.
    // Decides if the selection has changed (cursor moved) compared to the
    // previous values.
    //
    // After each keyup, the start/end values of the selection is compared to
    // the previously saved editing state.
    subscriptions.add(
        DomSubscription(
            activeDomElement,
            'keyup',
            allowInterop((DomEvent event) {
              handleChange(event);
            })));

    // In Firefox the context menu item "Select All" does not work without
    // listening to onSelect. On the other browsers onSelectionChange is
    // enough for covering "Select All" functionality.
    subscriptions.add(
        DomSubscription(
            activeDomElement, 'select', allowInterop(handleChange)));

    // Refocus on the activeDomElement after blur, so that user can keep editing the
    // text field.
    subscriptions.add(
        DomSubscription(
            activeDomElement,
            'blur',
            allowInterop((_) {
              _postponeFocus();
            })));

    preventDefaultForMouseEvents();
  }

  void _postponeFocus() {
    // Firefox does not focus on the editing element if we call the focus
    // inside the blur event, therefore we postpone the focus.
    // Calling focus inside a Timer for `0` milliseconds guarantee that it is
    // called after blur event propagation is completed.
    Timer(Duration.zero, () {
      activeDomElement.focus();
    });
  }

  @override
  void placeElement() {
    activeDomElement.focus();
    geometry?.applyToDomElement(activeDomElement);
    // Set the last editing state if it exists, this is critical for a
    // users ongoing work to continue uninterrupted when there is an update to
    // the transform.
    lastEditingState?.applyToDomElement(activeDomElement);
  }
}

/// Base class for all `TextInput` commands sent through the `flutter/textinput`
/// channel.
@immutable
abstract class TextInputCommand {
  const TextInputCommand();

  /// Executes the logic for this command.
  void run(HybridTextEditing textEditing);
}

/// Responds to the 'TextInput.setClient' message.
class TextInputSetClient extends TextInputCommand {
  const TextInputSetClient({
    required this.clientId,
    required this.configuration,
  });

  final int clientId;
  final InputConfiguration configuration;

  @override
  void run(HybridTextEditing textEditing) {
    final bool clientIdChanged = textEditing._clientId != null && textEditing._clientId != clientId;
    if (clientIdChanged && textEditing.isEditing) {
      // We're connecting a new client. Any pending command for the previous client
      // are irrelevant at this point.
      textEditing.stopEditing();
    }
    textEditing._clientId = clientId;
    textEditing.configuration = configuration;
  }
}

/// Creates the text editing strategy used in non-a11y mode.
DefaultTextEditingStrategy createDefaultTextEditingStrategy(HybridTextEditing textEditing) {
  DefaultTextEditingStrategy strategy;
  if (browserEngine == BrowserEngine.webkit &&
      operatingSystem == OperatingSystem.iOs) {
    strategy = IOSTextEditingStrategy(textEditing);
  } else if (browserEngine == BrowserEngine.webkit) {
    strategy = SafariDesktopTextEditingStrategy(textEditing);
  } else if (browserEngine == BrowserEngine.blink &&
      operatingSystem == OperatingSystem.android) {
    strategy = AndroidTextEditingStrategy(textEditing);
  } else if (browserEngine == BrowserEngine.firefox) {
    strategy = FirefoxTextEditingStrategy(textEditing);
  } else {
    strategy = GloballyPositionedTextEditingStrategy(textEditing);
  }
  return strategy;
}

/// Responds to the 'TextInput.updateConfig' message.
class TextInputUpdateConfig extends TextInputCommand {
  const TextInputUpdateConfig();

  @override
  void run(HybridTextEditing textEditing) {
    textEditing.strategy.applyConfiguration(textEditing.configuration!);
  }
}

/// Responds to the 'TextInput.setEditingState' message.
class TextInputSetEditingState extends TextInputCommand {
  const TextInputSetEditingState({
    required this.state,
  });

  final EditingState state;

  @override
  void run(HybridTextEditing textEditing) {
    textEditing.strategy.setEditingState(state);
  }
}

/// Responds to the 'TextInput.show' message.
class TextInputShow extends TextInputCommand {
  const TextInputShow();

  @override
  void run(HybridTextEditing textEditing) {
    if (!textEditing.isEditing) {
      textEditing._startEditing();
    }
  }
}

/// Responds to the 'TextInput.setEditableSizeAndTransform' message.
class TextInputSetEditableSizeAndTransform extends TextInputCommand {
  const TextInputSetEditableSizeAndTransform({
    required this.geometry,
  });

  final EditableTextGeometry geometry;

  @override
  void run(HybridTextEditing textEditing) {
    textEditing.strategy.updateElementPlacement(geometry);
  }
}

/// Responds to the 'TextInput.setStyle' message.
class TextInputSetStyle extends TextInputCommand {
  const TextInputSetStyle({
    required this.style,
  });

  final EditableTextStyle style;

  @override
  void run(HybridTextEditing textEditing) {
    textEditing.strategy.updateElementStyle(style);
  }
}

/// Responds to the 'TextInput.clearClient' message.
class TextInputClearClient extends TextInputCommand {
  const TextInputClearClient();

  @override
  void run(HybridTextEditing textEditing) {
    if (textEditing.isEditing) {
      textEditing.stopEditing();
    }
  }
}

/// Responds to the 'TextInput.hide' message.
class TextInputHide extends TextInputCommand {
  const TextInputHide();

  @override
  void run(HybridTextEditing textEditing) {
    if (textEditing.isEditing) {
      textEditing.stopEditing();
    }
  }
}

class TextInputSetMarkedTextRect extends TextInputCommand {
  const TextInputSetMarkedTextRect();

  @override
  void run(HybridTextEditing textEditing) {
    // No-op: this message is currently only used on iOS to implement
    // UITextInput.firstRecForRange.
  }
}

class TextInputSetCaretRect extends TextInputCommand {
  const TextInputSetCaretRect();

  @override
  void run(HybridTextEditing textEditing) {
    // No-op: not supported on this platform.
  }
}

class TextInputRequestAutofill extends TextInputCommand {
  const TextInputRequestAutofill();

  @override
  void run(HybridTextEditing textEditing) {
    // No-op: not supported on this platform.
  }
}

class TextInputFinishAutofillContext extends TextInputCommand {
  const TextInputFinishAutofillContext({
    required this.saveForm,
  });

  final bool saveForm;

  @override
  void run(HybridTextEditing textEditing) {
    // Close the text editing connection. Form is finalizing.
    textEditing.sendTextConnectionClosedToFrameworkIfAny();
    if (saveForm) {
      saveForms();
    }
    // Clean the forms from DOM after submitting them.
    cleanForms();
  }
}

/// Submits the forms currently attached to the DOM.
///
/// Browser will save the information entered to the form.
///
/// Called when the form is finalized with save option `true`.
/// See: https://github.com/flutter/flutter/blob/bf9f3a3dcfea3022f9cf2dfc3ab10b120b48b19d/packages/flutter/lib/src/services/text_input.dart#L1277
void saveForms() {
  formsOnTheDom.forEach((String identifier, DomHTMLFormElement form) {
    final DomHTMLInputElement submitBtn =
        form.getElementsByClassName('submitBtn').first as DomHTMLInputElement;
    submitBtn.click();
  });
}

/// Removes the forms from the DOM.
///
/// Called when the form is finalized.
void cleanForms() {
  for (final DomHTMLFormElement form in formsOnTheDom.values) {
    form.remove();
  }
  formsOnTheDom.clear();
}

/// Translates the message-based communication between the framework and the
/// engine [implementation].
///
/// This class is meant to be used as a singleton.
class TextEditingChannel {
  TextEditingChannel(this.implementation);

  /// Supplies the implementation that responds to the channel messages.
  final HybridTextEditing implementation;

  /// Handles "flutter/textinput" platform messages received from the framework.
  void handleTextInput(
      ByteData? data, ui.PlatformMessageResponseCallback? callback) {
    const JSONMethodCodec codec = JSONMethodCodec();
    final MethodCall call = codec.decodeMethodCall(data);
    final TextInputCommand command;
    switch (call.method) {
      case 'TextInput.setClient':
        command = TextInputSetClient(
          clientId: call.arguments[0] as int,
          configuration: InputConfiguration.fromFrameworkMessage(call.arguments[1] as Map<String, dynamic>),
        );
        break;

      case 'TextInput.updateConfig':
        // Set configuration eagerly because it contains data about the text
        // field used to flush the command queue. However, delaye applying the
        // configuration because the strategy may not be available yet.
        implementation.configuration = InputConfiguration.fromFrameworkMessage(
          call.arguments as Map<String, dynamic>
        );
        command = const TextInputUpdateConfig();
        break;

      case 'TextInput.setEditingState':
        command = TextInputSetEditingState(
          state: EditingState.fromFrameworkMessage(
            call.arguments as Map<String, dynamic>
          ),
        );
        break;

      case 'TextInput.show':
        command = const TextInputShow();
        break;

      case 'TextInput.setEditableSizeAndTransform':
        command = TextInputSetEditableSizeAndTransform(
          geometry: EditableTextGeometry.fromFrameworkMessage(
            call.arguments as Map<String, dynamic>
          ),
        );
        break;

      case 'TextInput.setStyle':
        command = TextInputSetStyle(
          style: EditableTextStyle.fromFrameworkMessage(
            call.arguments as Map<String, dynamic>,
          ),
        );
        break;

      case 'TextInput.clearClient':
        command = const TextInputClearClient();
        break;

      case 'TextInput.hide':
        command = const TextInputHide();
        break;

      case 'TextInput.requestAutofill':
        // There's no API to request autofill on the web. Instead we let the
        // browser show autofill options automatically, if available. We
        // therefore simply ignore this message.
        command = const TextInputRequestAutofill();
        break;

      case 'TextInput.finishAutofillContext':
        command = TextInputFinishAutofillContext(
          saveForm: call.arguments as bool,
        );
        break;

      case 'TextInput.setMarkedTextRect':
        command = const TextInputSetMarkedTextRect();
        break;

      case 'TextInput.setCaretRect':
        command = const TextInputSetCaretRect();
        break;

      default:
        EnginePlatformDispatcher.instance.replyToPlatformMessage(callback, null);
        return;
    }

    implementation.acceptCommand(command, () {
      EnginePlatformDispatcher.instance
          .replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
    });
  }

  /// Sends the 'TextInputClient.updateEditingState' message to the framework.
  void updateEditingState(int? clientId, EditingState? editingState) {
    EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
      'flutter/textinput',
      const JSONMethodCodec().encodeMethodCall(
        MethodCall('TextInputClient.updateEditingState', <dynamic>[
          clientId,
          editingState!.toFlutter(),
        ]),
      ),
      _emptyCallback,
    );
  }

  /// Sends the 'TextInputClient.updateEditingStateWithDeltas' message to the framework.
  void updateEditingStateWithDelta(int? clientId, TextEditingDeltaState? editingDeltaState) {
    EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
      'flutter/textinput',
      const JSONMethodCodec().encodeMethodCall(
        MethodCall('TextInputClient.updateEditingStateWithDeltas', <dynamic>[
          clientId,
          editingDeltaState!.toFlutter(),
        ]),
      ),
      _emptyCallback,
    );
  }

  /// Sends the 'TextInputClient.performAction' message to the framework.
  void performAction(int? clientId, String? inputAction) {
    EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
      'flutter/textinput',
      const JSONMethodCodec().encodeMethodCall(
        MethodCall(
          'TextInputClient.performAction',
          <dynamic>[clientId, inputAction],
        ),
      ),
      _emptyCallback,
    );
  }

  /// Sends the 'TextInputClient.onConnectionClosed' message to the framework.
  void onConnectionClosed(int? clientId) {
    EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
      'flutter/textinput',
      const JSONMethodCodec().encodeMethodCall(
        MethodCall(
          'TextInputClient.onConnectionClosed',
          <dynamic>[clientId],
        ),
      ),
      _emptyCallback,
    );
  }
}

/// Text editing singleton.
final HybridTextEditing textEditing = HybridTextEditing();

/// Map for storing forms left attached on the DOM.
///
/// Used for keeping the form elements on the DOM until user confirms to
/// save or cancel them.
///
/// See: https://github.com/flutter/flutter/blob/bf9f3a3dcfea3022f9cf2dfc3ab10b120b48b19d/packages/flutter/lib/src/services/text_input.dart#L1277
final Map<String, DomHTMLFormElement> formsOnTheDom =
    <String, DomHTMLFormElement>{};

/// Should be used as a singleton to provide support for text editing in
/// Flutter Web.
///
/// The approach is "hybrid" because it relies on Flutter for
/// displaying, and HTML for user interactions:
///
/// - HTML's contentEditable feature handles typing and text changes.
/// - HTML's selection API handles selection changes and cursor movements.
class HybridTextEditing {
  /// Private constructor so this class can be a singleton.
  ///
  /// The constructor also decides which text editing strategy to use depending
  /// on the operating system and browser engine.
  HybridTextEditing();

  late final TextEditingChannel channel = TextEditingChannel(this);

  /// A CSS class name used to identify all elements used for text editing.
  @visibleForTesting
  static const String textEditingClass = 'flt-text-editing';

  int? _clientId;

  /// Flag which shows if there is an ongoing editing.
  ///
  /// Also used to define if a keyboard is needed.
  bool isEditing = false;

  InputConfiguration? configuration;

  DefaultTextEditingStrategy? debugTextEditingStrategyOverride;

  /// Supplies the DOM element used for editing.
  late final DefaultTextEditingStrategy strategy =
    debugTextEditingStrategyOverride ??
    (EngineSemanticsOwner.instance.semanticsEnabled
      ? SemanticsTextEditingStrategy.ensureInitialized(this)
      : createDefaultTextEditingStrategy(this));

  void acceptCommand(TextInputCommand command, ui.VoidCallback callback) {
    if (_debugPrintTextInputCommands) {
      print('flutter/textinput channel command: ${command.runtimeType}');
    }
    command.run(this);
    callback();
  }

  void _startEditing() {
    assert(!isEditing);
    isEditing = true;
    strategy.enable(
      configuration!,
      onChange: (EditingState? editingState, TextEditingDeltaState? editingDeltaState) {
        if (configuration!.enableDeltaModel) {
          channel.updateEditingStateWithDelta(_clientId, editingDeltaState);
        } else {
          channel.updateEditingState(_clientId, editingState);
        }
      },
      onAction: (String? inputAction) {
        channel.performAction(_clientId, inputAction);
      },
    );
  }

  void stopEditing() {
    assert(isEditing);
    isEditing = false;
    strategy.disable();
  }

  void sendTextConnectionClosedToFrameworkIfAny() {
    if (isEditing) {
      stopEditing();
      channel.onConnectionClosed(_clientId);
    }
  }
}

/// Information on the font and alignment of a text editing element.
///
/// This information is received via TextInput.setStyle message.
class EditableTextStyle {
  EditableTextStyle({
    required this.textDirection,
    required this.fontSize,
    required this.textAlign,
    required this.fontFamily,
    required this.fontWeight,
  });

  factory EditableTextStyle.fromFrameworkMessage(
      Map<String, dynamic> flutterStyle) {
    assert(flutterStyle.containsKey('fontSize'));
    assert(flutterStyle.containsKey('fontFamily'));
    assert(flutterStyle.containsKey('textAlignIndex'));
    assert(flutterStyle.containsKey('textDirectionIndex'));

    final int textAlignIndex = flutterStyle['textAlignIndex'] as int;
    final int textDirectionIndex = flutterStyle['textDirectionIndex'] as int;
    final int? fontWeightIndex = flutterStyle['fontWeightIndex'] as int?;

    // Convert [fontWeightIndex] to its CSS equivalent value.
    final String fontWeight = fontWeightIndex != null
        ? fontWeightIndexToCss(fontWeightIndex: fontWeightIndex)
        : 'normal';

    // Also convert [textAlignIndex] and [textDirectionIndex] to their
    // corresponding enum values in [ui.TextAlign] and [ui.TextDirection]
    // respectively.
    return EditableTextStyle(
      fontSize: flutterStyle.tryDouble('fontSize'),
      fontFamily: flutterStyle.tryString('fontFamily'),
      textAlign: ui.TextAlign.values[textAlignIndex],
      textDirection: ui.TextDirection.values[textDirectionIndex],
      fontWeight: fontWeight,
    );
  }

  /// This information will be used for changing the style of the hidden input
  /// element, which will match it's size to the size of the editable widget.
  final double? fontSize;
  final String fontWeight;
  final String? fontFamily;
  final ui.TextAlign textAlign;
  final ui.TextDirection textDirection;

  String? get align => textAlignToCssValue(textAlign, textDirection);

  String get cssFont =>
      '$fontWeight ${fontSize}px ${canonicalizeFontFamily(fontFamily)}';

  void applyToDomElement(DomHTMLElement domElement) {
    domElement.style
      ..textAlign = align!
      ..font = cssFont;
  }
}

/// Describes the location and size of the editing element on the screen.
///
/// This information is received via "TextInput.setEditableSizeAndTransform"
/// message from the framework.
@immutable
class EditableTextGeometry {
  const EditableTextGeometry({
    required this.width,
    required this.height,
    required this.globalTransform,
  });

  /// Parses the geometry from a message sent by the framework.
  factory EditableTextGeometry.fromFrameworkMessage(
    Map<String, dynamic> encodedGeometry,
  ) {
    assert(encodedGeometry.containsKey('width'));
    assert(encodedGeometry.containsKey('height'));
    assert(encodedGeometry.containsKey('transform'));

    final List<double> transformList =
        List<double>.from(encodedGeometry.readList('transform').map(
          (final dynamic e) => (e as num).toDouble()
        ));
    return EditableTextGeometry(
      width: encodedGeometry.readDouble('width'),
      height: encodedGeometry.readDouble('height'),
      globalTransform: Float32List.fromList(transformList),
    );
  }

  /// The width of the editable in local coordinates, i.e. before applying [globalTransform].
  final double width;

  /// The height of the editable in local coordinates, i.e. before applying [globalTransform].
  final double height;

  /// The aggregate transform rooted at the global (screen) coordinate system
  /// that places and sizes the editable.
  ///
  /// For correct sizing this transform must be applied to the [width] and
  /// [height] fields.
  final Float32List globalTransform;

  /// Applies this geometry to the DOM element.
  ///
  /// This assumes that the parent of the [domElement] has identity transform
  /// applied to it (i.e. the default). If the parent has a non-identity
  /// transform applied, this method will misplace the [domElement]. For
  /// example, if the editable DOM element is nested inside the semantics
  /// tree the semantics tree provides the placement parameters, in which
  /// case this method should not be used.
  void applyToDomElement(DomHTMLElement domElement) {
    final String cssTransform = float64ListToCssTransform(globalTransform);
    domElement.style
      ..width = '${width}px'
      ..height = '${height}px'
      ..transform = cssTransform;
  }
}
