package com.android.launcher3;

import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

/**
 * Helper for identifying when a stylus touches a view while the primary stylus button is pressed.
 * This can occur in {@value MotionEvent#ACTION_DOWN} or {@value MotionEvent#ACTION_MOVE}. On a
 * stylus button press this performs the view's {@link View#performLongClick()} method, if the view
 * is long clickable.
 */
public class StylusEventHelper {
    private boolean mIsButtonPressed;
    private View mView;

    public StylusEventHelper(View view) {
        mView = view;
    }

    /**
     * Call this in onTouchEvent method of a view to identify a stylus button press and perform a
     * long click (if the view is long clickable).
     *
     * @param event The event to check for a stylus button press.
     * @return Whether a stylus event occurred and was handled.
     */
    public boolean checkAndPerformStylusEvent(MotionEvent event) {
        final float slop = ViewConfiguration.get(mView.getContext()).getScaledTouchSlop();

        if (!mView.isLongClickable()) {
            // We don't do anything unless the view is long clickable.
            return false;
        }

        final boolean stylusButtonPressed = isStylusButtonPressed(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mIsButtonPressed = false;
                if (stylusButtonPressed && mView.performLongClick()) {
                    mIsButtonPressed = true;
                    return true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (Utilities.pointInView(mView, event.getX(), event.getY(), slop)) {
                    if (!mIsButtonPressed && stylusButtonPressed && mView.performLongClick()) {
                        mIsButtonPressed = true;
                        return true;
                    } else if (mIsButtonPressed && !stylusButtonPressed) {
                        mIsButtonPressed = false;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mIsButtonPressed = false;
                break;
        }
        return false;
    }

    /**
     * Whether a stylus button press is occurring.
     */
    public boolean inStylusButtonPressed() {
        return mIsButtonPressed;
    }

    /**
     * Identifies if the provided {@link MotionEvent} is a stylus with the primary stylus button
     * pressed.
     *
     * @param event The event to check.
     * @return Whether a stylus button press occurred.
     */
    private static boolean isStylusButtonPressed(MotionEvent event) {
        return event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
                && ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY)
                        == MotionEvent.BUTTON_SECONDARY);
    }
}