// 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.

package io.flutter.plugin.editing;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.Editable;
import android.text.InputType;
import android.text.Selection;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewStructure;
import android.view.WindowInsets;
import android.view.WindowInsetsAnimation;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import io.flutter.embedding.engine.systemchannels.TextInputChannel;
import io.flutter.plugin.platform.PlatformViewsController;
import java.util.HashMap;
import java.util.List;

/** Android implementation of the text input plugin. */
public class TextInputPlugin {
  @NonNull private final View mView;
  @NonNull private final InputMethodManager mImm;
  @NonNull private final AutofillManager afm;
  @NonNull private final TextInputChannel textInputChannel;
  @NonNull private InputTarget inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, 0);
  @Nullable private TextInputChannel.Configuration configuration;
  @Nullable private SparseArray<TextInputChannel.Configuration> mAutofillConfigurations;
  @Nullable private Editable mEditable;
  private boolean mRestartInputPending;
  @Nullable private InputConnection lastInputConnection;
  @NonNull private PlatformViewsController platformViewsController;
  @Nullable private Rect lastClientRect;
  private final boolean restartAlwaysRequired;
  private ImeSyncDeferringInsetsCallback imeSyncCallback;

  // When true following calls to createInputConnection will return the cached lastInputConnection
  // if the input
  // target is a platform view. See the comments on lockPlatformViewInputConnection for more
  // details.
  private boolean isInputConnectionLocked;

  @SuppressLint("NewApi")
  public TextInputPlugin(
      View view,
      @NonNull TextInputChannel textInputChannel,
      @NonNull PlatformViewsController platformViewsController) {
    mView = view;
    mImm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      afm = view.getContext().getSystemService(AutofillManager.class);
    } else {
      afm = null;
    }

    // Sets up syncing ime insets with the framework, allowing
    // the Flutter view to grow and shrink to accomodate Android
    // controlled keyboard animations.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
      int mask = 0;
      if ((View.SYSTEM_UI_FLAG_HIDE_NAVIGATION & mView.getWindowSystemUiVisibility()) == 0) {
        mask = mask | WindowInsets.Type.navigationBars();
      }
      if ((View.SYSTEM_UI_FLAG_FULLSCREEN & mView.getWindowSystemUiVisibility()) == 0) {
        mask = mask | WindowInsets.Type.statusBars();
      }
      imeSyncCallback =
          new ImeSyncDeferringInsetsCallback(
              view,
              mask, // Overlay, insets that should be merged with the deferred insets
              WindowInsets.Type.ime() // Deferred, insets that will animate
              );
      mView.setWindowInsetsAnimationCallback(imeSyncCallback);
      mView.setOnApplyWindowInsetsListener(imeSyncCallback);
    }

    this.textInputChannel = textInputChannel;
    textInputChannel.setTextInputMethodHandler(
        new TextInputChannel.TextInputMethodHandler() {
          @Override
          public void show() {
            showTextInput(mView);
          }

          @Override
          public void hide() {
            hideTextInput(mView);
          }

          @Override
          public void requestAutofill() {
            notifyViewEntered();
          }

          @Override
          public void finishAutofillContext(boolean shouldSave) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || afm == null) {
              return;
            }
            if (shouldSave) {
              afm.commit();
            } else {
              afm.cancel();
            }
          }

          @Override
          public void setClient(
              int textInputClientId, TextInputChannel.Configuration configuration) {
            setTextInputClient(textInputClientId, configuration);
          }

          @Override
          public void setPlatformViewClient(int platformViewId) {
            setPlatformViewTextInputClient(platformViewId);
          }

          @Override
          public void setEditingState(TextInputChannel.TextEditState editingState) {
            setTextInputEditingState(mView, editingState);
          }

          @Override
          public void setEditableSizeAndTransform(double width, double height, double[] transform) {
            saveEditableSizeAndTransform(width, height, transform);
          }

          @Override
          public void clearClient() {
            clearTextInputClient();
          }

          @Override
          public void sendAppPrivateCommand(String action, Bundle data) {
            sendTextInputAppPrivateCommand(action, data);
          }
        });

    textInputChannel.requestExistingInputState();

    this.platformViewsController = platformViewsController;
    this.platformViewsController.attachTextInputPlugin(this);
    restartAlwaysRequired = isRestartAlwaysRequired();
  }

  // Loosely based off of
  // https://github.com/android/user-interface-samples/blob/master/WindowInsetsAnimation/app/src/main/java/com/google/android/samples/insetsanimation/RootViewDeferringInsetsCallback.kt
  //
  // When the IME is shown or hidden, it immediately sends an onApplyWindowInsets call
  // with the final state of the IME. This initial call disrupts the animation, which
  // causes a flicker in the beginning.
  //
  // To fix this, this class extends WindowInsetsAnimation.Callback and implements
  // OnApplyWindowInsetsListener. We capture and defer the initial call to
  // onApplyWindowInsets while the animation completes. When the animation
  // finishes, we can then release the call by invoking it in the onEnd callback
  //
  // The WindowInsetsAnimation.Callback extension forwards the new state of the
  // IME inset from onProgress() to the framework. We also make use of the
  // onStart callback to detect which calls to onApplyWindowInsets would
  // interrupt the animation and defer it.
  //
  // By implementing OnApplyWindowInsetsListener, we are able to capture Android's
  // attempts to call the FlutterView's onApplyWindowInsets. When a call to onStart
  // occurs, we can mark any non-animation calls to onApplyWindowInsets() that
  // occurs between prepare and start as deferred by using this class' wrapper
  // implementation to cache the WindowInsets passed in and turn the current call into
  // a no-op. When onEnd indicates the end of the animation, the deferred call is
  // dispatched again, this time avoiding any flicker since the animation is now
  // complete.
  @VisibleForTesting
  @TargetApi(30)
  @RequiresApi(30)
  @SuppressLint({"NewApi", "Override"})
  class ImeSyncDeferringInsetsCallback extends WindowInsetsAnimation.Callback
      implements View.OnApplyWindowInsetsListener {
    private int overlayInsetTypes;
    private int deferredInsetTypes;

    private View view;
    private WindowInsets lastWindowInsets;
    private boolean started = false;

    ImeSyncDeferringInsetsCallback(
        @NonNull View view, int overlayInsetTypes, int deferredInsetTypes) {
      super(WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE);
      this.overlayInsetTypes = overlayInsetTypes;
      this.deferredInsetTypes = deferredInsetTypes;
      this.view = view;
    }

    @Override
    public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
      this.view = view;
      if (started) {
        // While animation is running, we consume the insets to prevent disrupting
        // the animation, which skips this implementation and calls the view's
        // onApplyWindowInsets directly to avoid being consumed here.
        return WindowInsets.CONSUMED;
      }

      // Store the view and insets for us in onEnd() below
      lastWindowInsets = windowInsets;

      // If no animation is happening, pass the insets on to the view's own
      // inset handling.
      return view.onApplyWindowInsets(windowInsets);
    }

    @Override
    public WindowInsetsAnimation.Bounds onStart(
        WindowInsetsAnimation animation, WindowInsetsAnimation.Bounds bounds) {
      if ((animation.getTypeMask() & deferredInsetTypes) != 0) {
        started = true;
      }
      return bounds;
    }

    @Override
    public WindowInsets onProgress(
        WindowInsets insets, List<WindowInsetsAnimation> runningAnimations) {
      if (!started) {
        return insets;
      }
      boolean matching = false;
      for (WindowInsetsAnimation animation : runningAnimations) {
        if ((animation.getTypeMask() & deferredInsetTypes) != 0) {
          matching = true;
          continue;
        }
      }
      if (!matching) {
        return insets;
      }
      WindowInsets.Builder builder = new WindowInsets.Builder(lastWindowInsets);
      // Overlay the ime-only insets with the full insets.
      //
      // The IME insets passed in by onProgress assumes that the entire animation
      // occurs above any present navigation and status bars. This causes the
      // IME inset to be too large for the animation. To remedy this, we merge the
      // IME inset with other insets present via a subtract + reLu, which causes the
      // IME inset to be overlaid with any bars present.
      Insets newImeInsets =
          Insets.of(
              0,
              0,
              0,
              Math.max(
                  insets.getInsets(deferredInsetTypes).bottom
                      - insets.getInsets(overlayInsetTypes).bottom,
                  0));
      builder.setInsets(deferredInsetTypes, newImeInsets);
      // Directly call onApplyWindowInsets of the view as we do not want to pass through
      // the onApplyWindowInsets defined in this class, which would consume the insets
      // as if they were a non-animation inset change and cache it for re-dispatch in
      // onEnd instead.
      view.onApplyWindowInsets(builder.build());
      return insets;
    }

    @Override
    public void onEnd(WindowInsetsAnimation animation) {
      if (started && (animation.getTypeMask() & deferredInsetTypes) != 0) {
        // If we deferred the IME insets and an IME animation has finished, we need to reset
        // the flags
        started = false;

        // And finally dispatch the deferred insets to the view now.
        // Ideally we would just call view.requestApplyInsets() and let the normal dispatch
        // cycle happen, but this happens too late resulting in a visual flicker.
        // Instead we manually dispatch the most recent WindowInsets to the view.
        if (lastWindowInsets != null && view != null) {
          view.dispatchApplyWindowInsets(lastWindowInsets);
        }
      }
    }
  }

  @NonNull
  public InputMethodManager getInputMethodManager() {
    return mImm;
  }

  @VisibleForTesting
  Editable getEditable() {
    return mEditable;
  }

  @VisibleForTesting
  ImeSyncDeferringInsetsCallback getImeSyncCallback() {
    return imeSyncCallback;
  }

  /**
   * Use the current platform view input connection until unlockPlatformViewInputConnection is
   * called.
   *
   * <p>The current input connection instance is cached and any following call to @{link
   * createInputConnection} returns the cached connection until unlockPlatformViewInputConnection is
   * called.
   *
   * <p>This is a no-op if the current input target isn't a platform view.
   *
   * <p>This is used to preserve an input connection when moving a platform view from one virtual
   * display to another.
   */
  public void lockPlatformViewInputConnection() {
    if (inputTarget.type == InputTarget.Type.PLATFORM_VIEW) {
      isInputConnectionLocked = true;
    }
  }

  /**
   * Unlocks the input connection.
   *
   * <p>See also: @{link lockPlatformViewInputConnection}.
   */
  public void unlockPlatformViewInputConnection() {
    isInputConnectionLocked = false;
  }

  /**
   * Detaches the text input plugin from the platform views controller.
   *
   * <p>The TextInputPlugin instance should not be used after calling this.
   */
  @SuppressLint("NewApi")
  public void destroy() {
    platformViewsController.detachTextInputPlugin();
    textInputChannel.setTextInputMethodHandler(null);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
      mView.setWindowInsetsAnimationCallback(null);
      mView.setOnApplyWindowInsetsListener(null);
    }
  }

  private static int inputTypeFromTextInputType(
      TextInputChannel.InputType type,
      boolean obscureText,
      boolean autocorrect,
      boolean enableSuggestions,
      TextInputChannel.TextCapitalization textCapitalization) {
    if (type.type == TextInputChannel.TextInputType.DATETIME) {
      return InputType.TYPE_CLASS_DATETIME;
    } else if (type.type == TextInputChannel.TextInputType.NUMBER) {
      int textType = InputType.TYPE_CLASS_NUMBER;
      if (type.isSigned) {
        textType |= InputType.TYPE_NUMBER_FLAG_SIGNED;
      }
      if (type.isDecimal) {
        textType |= InputType.TYPE_NUMBER_FLAG_DECIMAL;
      }
      return textType;
    } else if (type.type == TextInputChannel.TextInputType.PHONE) {
      return InputType.TYPE_CLASS_PHONE;
    }

    int textType = InputType.TYPE_CLASS_TEXT;
    if (type.type == TextInputChannel.TextInputType.MULTILINE) {
      textType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE;
    } else if (type.type == TextInputChannel.TextInputType.EMAIL_ADDRESS) {
      textType |= InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
    } else if (type.type == TextInputChannel.TextInputType.URL) {
      textType |= InputType.TYPE_TEXT_VARIATION_URI;
    } else if (type.type == TextInputChannel.TextInputType.VISIBLE_PASSWORD) {
      textType |= InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
    } else if (type.type == TextInputChannel.TextInputType.NAME) {
      textType |= InputType.TYPE_TEXT_VARIATION_PERSON_NAME;
    } else if (type.type == TextInputChannel.TextInputType.POSTAL_ADDRESS) {
      textType |= InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS;
    }

    if (obscureText) {
      // Note: both required. Some devices ignore TYPE_TEXT_FLAG_NO_SUGGESTIONS.
      textType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
      textType |= InputType.TYPE_TEXT_VARIATION_PASSWORD;
    } else {
      if (autocorrect) textType |= InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
      if (!enableSuggestions) textType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
    }

    if (textCapitalization == TextInputChannel.TextCapitalization.CHARACTERS) {
      textType |= InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
    } else if (textCapitalization == TextInputChannel.TextCapitalization.WORDS) {
      textType |= InputType.TYPE_TEXT_FLAG_CAP_WORDS;
    } else if (textCapitalization == TextInputChannel.TextCapitalization.SENTENCES) {
      textType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
    }

    return textType;
  }

  public InputConnection createInputConnection(View view, EditorInfo outAttrs) {
    if (inputTarget.type == InputTarget.Type.NO_TARGET) {
      lastInputConnection = null;
      return null;
    }

    if (inputTarget.type == InputTarget.Type.PLATFORM_VIEW) {
      if (isInputConnectionLocked) {
        return lastInputConnection;
      }
      lastInputConnection =
          platformViewsController
              .getPlatformViewById(inputTarget.id)
              .onCreateInputConnection(outAttrs);
      return lastInputConnection;
    }

    outAttrs.inputType =
        inputTypeFromTextInputType(
            configuration.inputType,
            configuration.obscureText,
            configuration.autocorrect,
            configuration.enableSuggestions,
            configuration.textCapitalization);
    outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
    int enterAction;
    if (configuration.inputAction == null) {
      // If an explicit input action isn't set, then default to none for multi-line fields
      // and done for single line fields.
      enterAction =
          (InputType.TYPE_TEXT_FLAG_MULTI_LINE & outAttrs.inputType) != 0
              ? EditorInfo.IME_ACTION_NONE
              : EditorInfo.IME_ACTION_DONE;
    } else {
      enterAction = configuration.inputAction;
    }
    if (configuration.actionLabel != null) {
      outAttrs.actionLabel = configuration.actionLabel;
      outAttrs.actionId = enterAction;
    }
    outAttrs.imeOptions |= enterAction;

    InputConnectionAdaptor connection =
        new InputConnectionAdaptor(view, inputTarget.id, textInputChannel, mEditable, outAttrs);
    outAttrs.initialSelStart = Selection.getSelectionStart(mEditable);
    outAttrs.initialSelEnd = Selection.getSelectionEnd(mEditable);

    lastInputConnection = connection;
    return lastInputConnection;
  }

  @Nullable
  public InputConnection getLastInputConnection() {
    return lastInputConnection;
  }

  /**
   * Clears a platform view text input client if it is the current input target.
   *
   * <p>This is called when a platform view is disposed to make sure we're not hanging to a stale
   * input connection.
   */
  public void clearPlatformViewClient(int platformViewId) {
    if (inputTarget.type == InputTarget.Type.PLATFORM_VIEW && inputTarget.id == platformViewId) {
      inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, 0);
      hideTextInput(mView);
      mImm.restartInput(mView);
      mRestartInputPending = false;
    }
  }

  public void sendTextInputAppPrivateCommand(String action, Bundle data) {
    mImm.sendAppPrivateCommand(mView, action, data);
  }

  private void showTextInput(View view) {
    view.requestFocus();
    mImm.showSoftInput(view, 0);
  }

  private void hideTextInput(View view) {
    notifyViewExited();
    // Note: a race condition may lead to us hiding the keyboard here just after a platform view has
    // shown it.
    // This can only potentially happen when switching focus from a Flutter text field to a platform
    // view's text
    // field(by text field here I mean anything that keeps the keyboard open).
    // See: https://github.com/flutter/flutter/issues/34169
    mImm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
  }

  private void notifyViewEntered() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || afm == null || !needsAutofill()) {
      return;
    }

    final String triggerIdentifier = configuration.autofill.uniqueIdentifier;
    final int[] offset = new int[2];
    mView.getLocationOnScreen(offset);
    Rect rect = new Rect(lastClientRect);
    rect.offset(offset[0], offset[1]);
    afm.notifyViewEntered(mView, triggerIdentifier.hashCode(), rect);
  }

  private void notifyViewExited() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O
        || afm == null
        || configuration == null
        || configuration.autofill == null) {
      return;
    }

    final String triggerIdentifier = configuration.autofill.uniqueIdentifier;
    afm.notifyViewExited(mView, triggerIdentifier.hashCode());
  }

  private void notifyValueChanged(String newValue) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || afm == null || !needsAutofill()) {
      return;
    }

    final String triggerIdentifier = configuration.autofill.uniqueIdentifier;
    afm.notifyValueChanged(mView, triggerIdentifier.hashCode(), AutofillValue.forText(newValue));
  }

  @VisibleForTesting
  void setTextInputClient(int client, TextInputChannel.Configuration configuration) {
    inputTarget = new InputTarget(InputTarget.Type.FRAMEWORK_CLIENT, client);
    updateAutofillConfigurationIfNeeded(configuration);
    mEditable = Editable.Factory.getInstance().newEditable("");

    // setTextInputClient will be followed by a call to setTextInputEditingState.
    // Do a restartInput at that time.
    mRestartInputPending = true;
    unlockPlatformViewInputConnection();
    lastClientRect = null;
  }

  private void setPlatformViewTextInputClient(int platformViewId) {
    // We need to make sure that the Flutter view is focused so that no imm operations get short
    // circuited.
    // Not asking for focus here specifically manifested in a but on API 28 devices where the
    // platform view's
    // request to show a keyboard was ignored.
    mView.requestFocus();
    inputTarget = new InputTarget(InputTarget.Type.PLATFORM_VIEW, platformViewId);
    mImm.restartInput(mView);
    mRestartInputPending = false;
  }

  private void applyStateToSelection(TextInputChannel.TextEditState state) {
    int selStart = state.selectionStart;
    int selEnd = state.selectionEnd;
    if (selStart >= 0
        && selStart <= mEditable.length()
        && selEnd >= 0
        && selEnd <= mEditable.length()) {
      Selection.setSelection(mEditable, selStart, selEnd);
    } else {
      Selection.removeSelection(mEditable);
    }
  }

  @VisibleForTesting
  void setTextInputEditingState(View view, TextInputChannel.TextEditState state) {
    // Always replace the contents of mEditable if the text differs
    if (!state.text.equals(mEditable.toString())) {
      mEditable.replace(0, mEditable.length(), state.text);
    }
    notifyValueChanged(mEditable.toString());
    // Always apply state to selection which handles updating the selection if needed.
    applyStateToSelection(state);
    InputConnection connection = getLastInputConnection();
    if (connection != null && connection instanceof InputConnectionAdaptor) {
      ((InputConnectionAdaptor) connection).markDirty();
    }
    // Use updateSelection to update imm on selection if it is not neccessary to restart.
    if (!restartAlwaysRequired && !mRestartInputPending) {
      mImm.updateSelection(
          mView,
          Math.max(Selection.getSelectionStart(mEditable), 0),
          Math.max(Selection.getSelectionEnd(mEditable), 0),
          BaseInputConnection.getComposingSpanStart(mEditable),
          BaseInputConnection.getComposingSpanEnd(mEditable));
      // Restart if there is a pending restart or the device requires a force restart
      // (see isRestartAlwaysRequired). Restarting will also update the selection.
    } else {
      mImm.restartInput(view);
      mRestartInputPending = false;
    }
  }

  private interface MinMax {
    void inspect(double x, double y);
  }

  private void saveEditableSizeAndTransform(double width, double height, double[] matrix) {
    final double[] minMax = new double[4]; // minX, maxX, minY, maxY.
    final boolean isAffine = matrix[3] == 0 && matrix[7] == 0 && matrix[15] == 1;
    minMax[0] = minMax[1] = matrix[12] / matrix[15]; // minX and maxX.
    minMax[2] = minMax[3] = matrix[13] / matrix[15]; // minY and maxY.

    final MinMax finder =
        new MinMax() {
          @Override
          public void inspect(double x, double y) {
            final double w = isAffine ? 1 : 1 / (matrix[3] * x + matrix[7] * y + matrix[15]);
            final double tx = (matrix[0] * x + matrix[4] * y + matrix[12]) * w;
            final double ty = (matrix[1] * x + matrix[5] * y + matrix[13]) * w;

            if (tx < minMax[0]) {
              minMax[0] = tx;
            } else if (tx > minMax[1]) {
              minMax[1] = tx;
            }

            if (ty < minMax[2]) {
              minMax[2] = ty;
            } else if (ty > minMax[3]) {
              minMax[3] = ty;
            }
          }
        };

    finder.inspect(width, 0);
    finder.inspect(width, height);
    finder.inspect(0, height);
    final Float density = mView.getContext().getResources().getDisplayMetrics().density;
    lastClientRect =
        new Rect(
            (int) (minMax[0] * density),
            (int) (minMax[2] * density),
            (int) Math.ceil(minMax[1] * density),
            (int) Math.ceil(minMax[3] * density));
  }

  private void updateAutofillConfigurationIfNeeded(TextInputChannel.Configuration configuration) {
    notifyViewExited();
    this.configuration = configuration;
    final TextInputChannel.Configuration[] configurations = configuration.fields;

    if (configuration.autofill == null) {
      // Disables autofill if the configuration doesn't have an autofill field.
      mAutofillConfigurations = null;
      return;
    }

    mAutofillConfigurations = new SparseArray<>();

    if (configurations == null) {
      mAutofillConfigurations.put(
          configuration.autofill.uniqueIdentifier.hashCode(), configuration);
    } else {
      for (TextInputChannel.Configuration config : configurations) {
        TextInputChannel.Configuration.Autofill autofill = config.autofill;
        if (autofill == null) {
          continue;
        }

        mAutofillConfigurations.put(autofill.uniqueIdentifier.hashCode(), config);
      }
    }
  }

  private boolean needsAutofill() {
    return mAutofillConfigurations != null;
  }

  public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || !needsAutofill()) {
      return;
    }

    final String triggerIdentifier = configuration.autofill.uniqueIdentifier;
    final AutofillId parentId = structure.getAutofillId();
    for (int i = 0; i < mAutofillConfigurations.size(); i++) {
      final int autofillId = mAutofillConfigurations.keyAt(i);
      final TextInputChannel.Configuration config = mAutofillConfigurations.valueAt(i);
      final TextInputChannel.Configuration.Autofill autofill = config.autofill;
      if (autofill == null) {
        continue;
      }

      structure.addChildCount(1);
      final ViewStructure child = structure.newChild(i);
      child.setAutofillId(parentId, autofillId);
      child.setAutofillValue(AutofillValue.forText(autofill.editState.text));
      child.setAutofillHints(autofill.hints);
      child.setAutofillType(View.AUTOFILL_TYPE_TEXT);
      child.setVisibility(View.VISIBLE);

      // Some autofill services expect child structures to be visible.
      // Reports the real size of the child if it's the current client.
      if (triggerIdentifier.hashCode() == autofillId && lastClientRect != null) {
        child.setDimens(
            lastClientRect.left,
            lastClientRect.top,
            0,
            0,
            lastClientRect.width(),
            lastClientRect.height());
      } else {
        // Reports a fake dimension that's still visible.
        child.setDimens(0, 0, 0, 0, 1, 1);
      }
    }
  }

  public void autofill(SparseArray<AutofillValue> values) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
      return;
    }

    final TextInputChannel.Configuration.Autofill currentAutofill = configuration.autofill;
    if (currentAutofill == null) {
      return;
    }

    final HashMap<String, TextInputChannel.TextEditState> editingValues = new HashMap<>();
    for (int i = 0; i < values.size(); i++) {
      int virtualId = values.keyAt(i);

      final TextInputChannel.Configuration config = mAutofillConfigurations.get(virtualId);
      if (config == null || config.autofill == null) {
        continue;
      }

      final TextInputChannel.Configuration.Autofill autofill = config.autofill;
      final String value = values.valueAt(i).getTextValue().toString();
      final TextInputChannel.TextEditState newState =
          new TextInputChannel.TextEditState(value, value.length(), value.length());

      // The value of the currently focused text field needs to be updated.
      if (autofill.uniqueIdentifier.equals(currentAutofill.uniqueIdentifier)) {
        setTextInputEditingState(mView, newState);
      }
      editingValues.put(autofill.uniqueIdentifier, newState);
    }

    textInputChannel.updateEditingStateWithTag(inputTarget.id, editingValues);
  }

  // Samsung's Korean keyboard has a bug where it always attempts to combine characters based on
  // its internal state, ignoring if and when the cursor is moved programmatically. The same bug
  // also causes non-korean keyboards to occasionally duplicate text when tapping in the middle
  // of existing text to edit it.
  //
  // Fully restarting the IMM works around this because it flushes the keyboard's internal state
  // and stops it from trying to incorrectly combine characters. However this also has some
  // negative performance implications, so we don't want to apply this workaround in every case.
  @SuppressLint("NewApi") // New API guard is inline, the linter can't see it.
  @SuppressWarnings("deprecation")
  private boolean isRestartAlwaysRequired() {
    InputMethodSubtype subtype = mImm.getCurrentInputMethodSubtype();
    // Impacted devices all shipped with Android Lollipop or newer.
    if (subtype == null
        || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP
        || !Build.MANUFACTURER.equals("samsung")) {
      return false;
    }
    String keyboardName =
        Settings.Secure.getString(
            mView.getContext().getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
    // The Samsung keyboard is called "com.sec.android.inputmethod/.SamsungKeypad" but look
    // for "Samsung" just in case Samsung changes the name of the keyboard.
    return keyboardName.contains("Samsung");
  }

  private void clearTextInputClient() {
    if (inputTarget.type == InputTarget.Type.PLATFORM_VIEW) {
      // Focus changes in the framework tree have no guarantees on the order focus nodes are
      // notified. A node
      // that lost focus may be notified before or after a node that gained focus.
      // When moving the focus from a Flutter text field to an AndroidView, it is possible that the
      // Flutter text
      // field's focus node will be notified that it lost focus after the AndroidView was notified
      // that it gained
      // focus. When this happens the text field will send a clearTextInput command which we ignore.
      // By doing this we prevent the framework from clearing a platform view input client(the only
      // way to do so
      // is to set a new framework text client). I don't see an obvious use case for "clearing" a
      // platform views
      // text input client, and it may be error prone as we don't know how the platform view manages
      // the input
      // connection and we probably shouldn't interfere.
      // If we ever want to allow the framework to clear a platform view text client we should
      // probably consider
      // changing the focus manager such that focus nodes that lost focus are notified before focus
      // nodes that
      // gained focus as part of the same focus event.
      return;
    }
    inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, 0);
    unlockPlatformViewInputConnection();
    notifyViewExited();
    lastClientRect = null;
  }

  private static class InputTarget {
    enum Type {
      NO_TARGET,
      // InputConnection is managed by the TextInputPlugin, and events are forwarded to the Flutter
      // framework.
      FRAMEWORK_CLIENT,
      // InputConnection is managed by an embedded platform view.
      PLATFORM_VIEW
    }

    public InputTarget(@NonNull Type type, int id) {
      this.type = type;
      this.id = id;
    }

    @NonNull Type type;
    // The ID of the input target.
    //
    // For framework clients this is the framework input connection client ID.
    // For platform views this is the platform view's ID.
    int id;
  }
}
