/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

package com.facebook.drawee.gestures;

import android.content.Context;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import com.facebook.common.internal.VisibleForTesting;

/**
 * Gesture detector based on touch events.
 * <p>
 * This class allows us to get click events when we need them, but not to consume them when we are
 * temporarily not interested in them. Doing {@code View.setClickable(true)} will cause for the
 * view always to consume click event, even if {@code View.performClick} is overridden to return
 * false. That means even though our view didn't handle the click event, the event will not get
 * propagated upwards. Result of {@code View.onTouchEvent} is handled correctly though so we use
 * that instead.
 * <p> This class currently only detects clicks.
 */
public class GestureDetector {

  /** Interface for the click listener. */
  public interface ClickListener {
    public boolean onClick();
  }

  @VisibleForTesting ClickListener mClickListener;

  @VisibleForTesting final float mSingleTapSlopPx;
  @VisibleForTesting boolean mIsCapturingGesture;
  @VisibleForTesting boolean mIsClickCandidate;
  @VisibleForTesting long mActionDownTime;
  @VisibleForTesting float mActionDownX;
  @VisibleForTesting float mActionDownY;

  public GestureDetector(Context context) {
    final ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
    mSingleTapSlopPx = viewConfiguration.getScaledTouchSlop();
    init();
  }

  /** Creates a new instance of this gesture detector. */
  public static GestureDetector newInstance(Context context) {
    return new GestureDetector(context);
  }

  /** Initializes this component to its initial state. */
  public void init() {
    mClickListener = null;
    reset();
  }

  /**
   * Resets component.
   * <p> This will drop any gesture recognition that might currently be in progress.
   */
  public void reset() {
    mIsCapturingGesture = false;
    mIsClickCandidate = false;
  }

  /** Sets the click listener. */
  public void setClickListener(ClickListener clickListener) {
    mClickListener = clickListener;
  }

  /** Returns whether the gesture capturing is in progress. */
  public boolean isCapturingGesture() {
    return mIsCapturingGesture;
  }

  /** Handles the touch event */
  public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        mIsCapturingGesture = true;
        mIsClickCandidate = true;
        mActionDownTime = event.getEventTime();
        mActionDownX = event.getX();
        mActionDownY = event.getY();
        break;
      case MotionEvent.ACTION_MOVE:
        if (Math.abs(event.getX() - mActionDownX) > mSingleTapSlopPx ||
            Math.abs(event.getY() - mActionDownY) > mSingleTapSlopPx) {
          mIsClickCandidate = false;
        }
        break;
      case MotionEvent.ACTION_CANCEL:
        mIsCapturingGesture = false;
        mIsClickCandidate = false;
        break;
      case MotionEvent.ACTION_UP:
        mIsCapturingGesture = false;
        if (Math.abs(event.getX() - mActionDownX) > mSingleTapSlopPx ||
            Math.abs(event.getY() - mActionDownY) > mSingleTapSlopPx) {
          mIsClickCandidate = false;
        }
        if (mIsClickCandidate) {
          if (event.getEventTime() - mActionDownTime <= ViewConfiguration.getLongPressTimeout()) {
            if (mClickListener != null) {
              mClickListener.onClick();
            }
          } else {
            // long click, not handled
          }
        }
        mIsClickCandidate = false;
        break;
    }
    return true;
  }

}

@@ -379,16 +379,50 @@
 Testing;
+%0Aimport javax.annotation.Nullable;
 %0A%0A/**%0A *
@@ -1190,16 +1190,26 @@
 Testing 
+@Nullable 
 ClickLis

Fix the Nullsafe warnings on GestureDetector.java