// 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.text.Editable;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.view.View;
import android.view.inputmethod.BaseInputConnection;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.Log;
import io.flutter.embedding.engine.systemchannels.TextInputChannel;
import java.util.ArrayList;

/// The current editing state (text, selection range, composing range) the text input plugin holds.
///
/// As the name implies, this class also notifies its listeners when the editing state changes. When
/// there're ongoing batch edits, change notifications will be deferred until all batch edits end
/// (i.e. when the outermost batch edit ends). Listeners added during a batch edit will always be
/// notified when all batch edits end, even if there's no real change.
///
/// Adding/removing listeners or changing the editing state in a didChangeEditingState callback may
/// cause unexpected behavior.
//
// Currently this class does not notify its listeners on spans-only changes (e.g.,
// Selection.setSelection). Wrap them in a batch edit to trigger a change notification.
class ListenableEditingState extends SpannableStringBuilder {
  interface EditingStateWatcher {
    // Changing the editing state in a didChangeEditingState callback may cause unexpected
    // behavior.
    void didChangeEditingState(
        boolean textChanged, boolean selectionChanged, boolean composingRegionChanged);
  }

  private static final String TAG = "ListenableEditingState";

  private int mBatchEditNestDepth = 0;
  // We don't support adding/removing listeners, or changing the editing state in a listener
  // callback for now.
  private int mChangeNotificationDepth = 0;
  private ArrayList<EditingStateWatcher> mListeners = new ArrayList<>();
  private ArrayList<EditingStateWatcher> mPendingListeners = new ArrayList<>();
  private ArrayList<TextEditingDelta> mBatchTextEditingDeltas = new ArrayList<>();

  private String mToStringCache;

  private String mTextWhenBeginBatchEdit;
  private int mSelectionStartWhenBeginBatchEdit;
  private int mSelectionEndWhenBeginBatchEdit;
  private int mComposingStartWhenBeginBatchEdit;
  private int mComposingEndWhenBeginBatchEdit;

  private BaseInputConnection mDummyConnection;

  // The View is only used for creating a dummy BaseInputConnection for setComposingRegion. The View
  // needs to have a non-null Context.
  public ListenableEditingState(
      @Nullable TextInputChannel.TextEditState initialState, @NonNull View view) {
    super();

    Editable self = this;
    mDummyConnection =
        new BaseInputConnection(view, true) {
          @Override
          public Editable getEditable() {
            return self;
          }
        };

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

  public ArrayList<TextEditingDelta> extractBatchTextEditingDeltas() {
    ArrayList<TextEditingDelta> currentBatchDeltas =
        new ArrayList<TextEditingDelta>(mBatchTextEditingDeltas);
    mBatchTextEditingDeltas.clear();
    return currentBatchDeltas;
  }

  public void clearBatchDeltas() {
    mBatchTextEditingDeltas.clear();
  }

  /// Starts a new batch edit during which change notifications will be put on hold until all batch
  /// edits end.
  ///
  /// Batch edits nest.
  public void beginBatchEdit() {
    mBatchEditNestDepth++;
    if (mChangeNotificationDepth > 0) {
      Log.e(TAG, "editing state should not be changed in a listener callback");
    }
    if (mBatchEditNestDepth == 1 && !mListeners.isEmpty()) {
      mTextWhenBeginBatchEdit = toString();
      mSelectionStartWhenBeginBatchEdit = getSelectionStart();
      mSelectionEndWhenBeginBatchEdit = getSelectionEnd();
      mComposingStartWhenBeginBatchEdit = getComposingStart();
      mComposingEndWhenBeginBatchEdit = getComposingEnd();
    }
  }

  /// Ends the current batch edit and flush pending change notifications if the current batch edit
  /// is not nested (i.e. it is the last ongoing batch edit).
  public void endBatchEdit() {
    if (mBatchEditNestDepth == 0) {
      Log.e(TAG, "endBatchEdit called without a matching beginBatchEdit");
      return;
    }
    if (mBatchEditNestDepth == 1) {
      for (final EditingStateWatcher listener : mPendingListeners) {
        notifyListener(listener, true, true, true);
      }

      if (!mListeners.isEmpty()) {
        Log.v(TAG, "didFinishBatchEdit with " + String.valueOf(mListeners.size()) + " listener(s)");
        final boolean textChanged = !toString().equals(mTextWhenBeginBatchEdit);
        final boolean selectionChanged =
            mSelectionStartWhenBeginBatchEdit != getSelectionStart()
                || mSelectionEndWhenBeginBatchEdit != getSelectionEnd();
        final boolean composingRegionChanged =
            mComposingStartWhenBeginBatchEdit != getComposingStart()
                || mComposingEndWhenBeginBatchEdit != getComposingEnd();

        notifyListenersIfNeeded(textChanged, selectionChanged, composingRegionChanged);
      }
    }

    mListeners.addAll(mPendingListeners);
    mPendingListeners.clear();
    mBatchEditNestDepth--;
  }

  /// Update the composing region of the current editing state.
  ///
  /// If the range is invalid or empty, the current composing region will be removed.
  public void setComposingRange(int composingStart, int composingEnd) {
    if (composingStart < 0 || composingStart >= composingEnd) {
      BaseInputConnection.removeComposingSpans(this);
    } else {
      mDummyConnection.setComposingRegion(composingStart, composingEnd);
    }
  }

  /// Called when the framework sends updates to the text input plugin.
  ///
  /// This method will also update the composing region if it has changed.
  public void setEditingState(TextInputChannel.TextEditState newState) {
    beginBatchEdit();
    replace(0, length(), newState.text);

    if (newState.hasSelection()) {
      Selection.setSelection(this, newState.selectionStart, newState.selectionEnd);
    } else {
      Selection.removeSelection(this);
    }

    setComposingRange(newState.composingStart, newState.composingEnd);

    // Updates from the framework should not have a delta created for it as they have already been
    // applied on the framework side.
    clearBatchDeltas();

    endBatchEdit();
  }

  public void addEditingStateListener(EditingStateWatcher listener) {
    if (mChangeNotificationDepth > 0) {
      Log.e(TAG, "adding a listener " + listener.toString() + " in a listener callback");
    }
    // It is possible for a listener to get added during a batch edit. When that happens we always
    // notify the new listeners.
    // This does not check if the listener is already in the list of existing listeners.
    if (mBatchEditNestDepth > 0) {
      Log.w(TAG, "a listener was added to EditingState while a batch edit was in progress");
      mPendingListeners.add(listener);
    } else {
      mListeners.add(listener);
    }
  }

  public void removeEditingStateListener(EditingStateWatcher listener) {
    if (mChangeNotificationDepth > 0) {
      Log.e(TAG, "removing a listener " + listener.toString() + " in a listener callback");
    }
    mListeners.remove(listener);
    if (mBatchEditNestDepth > 0) {
      mPendingListeners.remove(listener);
    }
  }

  @Override
  public SpannableStringBuilder replace(
      int start, int end, CharSequence tb, int tbstart, int tbend) {

    if (mChangeNotificationDepth > 0) {
      Log.e(TAG, "editing state should not be changed in a listener callback");
    }

    final CharSequence oldText = toString();

    boolean textChanged = end - start != tbend - tbstart;
    for (int i = 0; i < end - start && !textChanged; i++) {
      textChanged |= charAt(start + i) != tb.charAt(tbstart + i);
    }
    if (textChanged) {
      mToStringCache = null;
    }

    final int selectionStart = getSelectionStart();
    final int selectionEnd = getSelectionEnd();
    final int composingStart = getComposingStart();
    final int composingEnd = getComposingEnd();

    final SpannableStringBuilder editable = super.replace(start, end, tb, tbstart, tbend);
    mBatchTextEditingDeltas.add(
        new TextEditingDelta(
            oldText,
            start,
            end,
            tb,
            getSelectionStart(),
            getSelectionEnd(),
            getComposingStart(),
            getComposingEnd()));

    if (mBatchEditNestDepth > 0) {
      return editable;
    }

    final boolean selectionChanged =
        getSelectionStart() != selectionStart || getSelectionEnd() != selectionEnd;
    final boolean composingRegionChanged =
        getComposingStart() != composingStart || getComposingEnd() != composingEnd;
    notifyListenersIfNeeded(textChanged, selectionChanged, composingRegionChanged);
    return editable;
  }

  private void notifyListener(
      EditingStateWatcher listener,
      boolean textChanged,
      boolean selectionChanged,
      boolean composingChanged) {
    mChangeNotificationDepth++;
    listener.didChangeEditingState(textChanged, selectionChanged, composingChanged);
    mChangeNotificationDepth--;
  }

  private void notifyListenersIfNeeded(
      boolean textChanged, boolean selectionChanged, boolean composingChanged) {
    if (textChanged || selectionChanged || composingChanged) {
      for (final EditingStateWatcher listener : mListeners) {
        notifyListener(listener, textChanged, selectionChanged, composingChanged);
      }
    }
  }

  public final int getSelectionStart() {
    return Selection.getSelectionStart(this);
  }

  public final int getSelectionEnd() {
    return Selection.getSelectionEnd(this);
  }

  public final int getComposingStart() {
    return BaseInputConnection.getComposingSpanStart(this);
  }

  public final int getComposingEnd() {
    return BaseInputConnection.getComposingSpanEnd(this);
  }

  @Override
  public void setSpan(Object what, int start, int end, int flags) {
    super.setSpan(what, start, end, flags);
    // Setting a span does not involve mutating the text value in the editing state. Here we create
    // a non text update delta with any updated selection and composing regions.
    mBatchTextEditingDeltas.add(
        new TextEditingDelta(
            toString(),
            getSelectionStart(),
            getSelectionEnd(),
            getComposingStart(),
            getComposingEnd()));
  }

  @Override
  public String toString() {
    return mToStringCache != null ? mToStringCache : (mToStringCache = super.toString());
  }
}
