package org.thoughtcrime.securesms.components;

import android.content.Context;
import android.os.Build;
import android.text.InputType;
import android.util.AttributeSet;
import android.widget.EditText;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout.OnKeyboardShownListener;
import org.thoughtcrime.securesms.util.ServiceUtil;

public class InputAwareLayout extends KeyboardAwareLinearLayout implements OnKeyboardShownListener {
  private InputView current;
  private int       previousInputType = InputType.TYPE_NULL;

  public InputAwareLayout(Context context) {
    this(context, null);
  }

  public InputAwareLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public InputAwareLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    addOnKeyboardShownListener(this);
  }

  @Override
  public void onKeyboardShown() {
  }

  public void show(@NonNull final EditText imeTarget, @NonNull final InputView input) {
    if (isKeyboardOpen()) {
      hideSoftkey(imeTarget, new Runnable() {
        @Override public void run() {
          hideAttachedInput(true);
          input.show(getKeyboardHeight(), true);
          current = input;
        }
      });
    } else {
      if (current != null) current.hide(true);
      input.show(getKeyboardHeight(), current != null);
      current = input;
    }

    setShowSoftInputOnFocusCompat(imeTarget, false);
  }

  public InputView getCurrentInput() {
    return current;
  }

  public void hideCurrentInput(EditText imeTarget) {
    if (isKeyboardOpen()) hideSoftkey(imeTarget, null);
    else                  hideAttachedInput(false);

    setShowSoftInputOnFocusCompat(imeTarget, true);
  }

  public void hideAttachedInput(boolean instant) {
    if (current != null) current.hide(instant);
    current = null;
  }

  public boolean isInputOpen() {
    return (isKeyboardOpen() || (current != null && current.isShowing()));
  }

  public void showSoftkey(final EditText inputTarget) {
    showSoftkey(inputTarget, false);
  }

  public void showSoftkey(final EditText inputTarget, boolean force) {
    if (!force && isInputOpen()) return;

    setShowSoftInputOnFocusCompat(inputTarget, true);
    postOnKeyboardOpen(new Runnable() {
      @Override public void run() {
        hideAttachedInput(true);
      }
    });
    inputTarget.post(new Runnable() {
      @Override public void run() {
        inputTarget.requestFocus();
        ServiceUtil.getInputMethodManager(inputTarget.getContext()).showSoftInput(inputTarget, 0);
      }
    });
  }

  public void hideSoftkey(final EditText inputTarget, @Nullable Runnable runAfterClose) {
    if (runAfterClose != null) postOnKeyboardClose(runAfterClose);

    ServiceUtil.getInputMethodManager(inputTarget.getContext())
               .hideSoftInputFromWindow(inputTarget.getWindowToken(), 0);
  }

  private void setShowSoftInputOnFocusCompat(EditText imeTarget, boolean show) {
    if (Build.VERSION.SDK_INT >= 21) {
      imeTarget.setShowSoftInputOnFocus(show);
    } else if (show) {
      if (previousInputType != InputType.TYPE_NULL) {
        imeTarget.setInputType(previousInputType);
      }
    } else {
      previousInputType = imeTarget.getInputType();
      imeTarget.setRawInputType(InputType.TYPE_CLASS_TEXT);
      imeTarget.setTextIsSelectable(true);
    }
  }

  public interface InputView {
    void show(int height, boolean immediate);
    void hide(boolean immediate);
    boolean isShowing();
  }
}

