/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.documentsui.dirlist;

import static com.android.documentsui.base.Shared.DEBUG;
import static com.android.documentsui.base.Shared.VERBOSE;

import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;

import com.android.documentsui.ActionHandler;
import com.android.documentsui.base.EventHandler;
import com.android.documentsui.base.Events;
import com.android.documentsui.base.Events.InputEvent;
import com.android.documentsui.selection.SelectionManager;

import java.util.Collections;
import java.util.function.Function;
import java.util.function.Predicate;

import javax.annotation.Nullable;

/**
 * Grand unified-ish gesture/event listener for items in the directory list.
 */
public final class UserInputHandler<T extends InputEvent>
        extends GestureDetector.SimpleOnGestureListener
        implements DocumentHolder.KeyboardEventListener {

    private static final String TAG = "UserInputHandler";

    private ActionHandler mActions;
    private final FocusHandler mFocusHandler;
    private final SelectionManager mSelectionMgr;
    private final Function<MotionEvent, T> mEventConverter;
    private final Predicate<DocumentDetails> mSelectable;

    private final EventHandler<InputEvent> mContextMenuClickHandler;

    private final EventHandler<InputEvent> mTouchDragListener;
    private final EventHandler<InputEvent> mGestureSelectHandler;

    private final TouchInputDelegate mTouchDelegate;
    private final MouseInputDelegate mMouseDelegate;
    private final KeyInputHandler mKeyListener;

    public UserInputHandler(
            ActionHandler actions,
            FocusHandler focusHandler,
            SelectionManager selectionMgr,
            Function<MotionEvent, T> eventConverter,
            Predicate<DocumentDetails> selectable,
            EventHandler<InputEvent> contextMenuClickHandler,
            EventHandler<InputEvent> touchDragListener,
            EventHandler<InputEvent> gestureSelectHandler) {

        mActions = actions;
        mFocusHandler = focusHandler;
        mSelectionMgr = selectionMgr;
        mEventConverter = eventConverter;
        mSelectable = selectable;
        mContextMenuClickHandler = contextMenuClickHandler;
        mTouchDragListener = touchDragListener;
        mGestureSelectHandler = gestureSelectHandler;

        mTouchDelegate = new TouchInputDelegate();
        mMouseDelegate = new MouseInputDelegate();
        mKeyListener = new KeyInputHandler();
    }

    @Override
    public boolean onDown(MotionEvent e) {
        try (T event = mEventConverter.apply(e)) {
            return onDown(event);
        }
    }

    @VisibleForTesting
    boolean onDown(T event) {
        return event.isMouseEvent()
                ? mMouseDelegate.onDown(event)
                : mTouchDelegate.onDown(event);
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2,
            float distanceX, float distanceY) {
        try (T event = mEventConverter.apply(e2)) {
            return onScroll(event);
        }
    }

    @VisibleForTesting
    boolean onScroll(T event) {
        return event.isMouseEvent()
                ? mMouseDelegate.onScroll(event)
                : mTouchDelegate.onScroll(event);
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        try (T event = mEventConverter.apply(e)) {
            return onSingleTapUp(event);
        }
    }

    @VisibleForTesting
    boolean onSingleTapUp(T event) {
        return event.isMouseEvent()
                ? mMouseDelegate.onSingleTapUp(event)
                : mTouchDelegate.onSingleTapUp(event);
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        try (T event = mEventConverter.apply(e)) {
            return onSingleTapConfirmed(event);
        }
    }

    @VisibleForTesting
    boolean onSingleTapConfirmed(T event) {
        return event.isMouseEvent()
                ? mMouseDelegate.onSingleTapConfirmed(event)
                : mTouchDelegate.onSingleTapConfirmed(event);
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        try (T event = mEventConverter.apply(e)) {
            return onDoubleTap(event);
        }
    }

    @VisibleForTesting
    boolean onDoubleTap(T event) {
        return event.isMouseEvent()
                ? mMouseDelegate.onDoubleTap(event)
                : mTouchDelegate.onDoubleTap(event);
    }

    @Override
    public void onLongPress(MotionEvent e) {
        try (T event = mEventConverter.apply(e)) {
            onLongPress(event);
        }
    }

    @VisibleForTesting
    void onLongPress(T event) {
        if (event.isMouseEvent()) {
            mMouseDelegate.onLongPress(event);
        } else {
            mTouchDelegate.onLongPress(event);
        }
    }

    // Only events from RecyclerView are fed into UserInputHandler#onDown.
    // ListeningGestureDetector#onTouch directly calls this method to support context menu in empty
    // view
    boolean onRightClick(MotionEvent e) {
        try (T event = mEventConverter.apply(e)) {
            return mMouseDelegate.onRightClick(event);
        }
    }

    @Override
    public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event) {
        return mKeyListener.onKey(doc, keyCode, event);
    }

    private boolean selectDocument(DocumentDetails doc) {
        assert(doc != null);
        assert(doc.hasModelId());
        mSelectionMgr.toggleSelection(doc.getModelId());
        mSelectionMgr.setSelectionRangeBegin(doc.getAdapterPosition());
        return true;
    }

    private void extendSelectionRange(DocumentDetails doc) {
        mSelectionMgr.snapRangeSelection(doc.getAdapterPosition());
    }

    boolean isRangeExtension(T event) {
        return event.isShiftKeyDown() && mSelectionMgr.isRangeSelectionActive();
    }

    private boolean shouldClearSelection(T event, DocumentDetails doc) {
        return !event.isCtrlKeyDown()
                && !doc.isInSelectionHotspot(event)
                && !mSelectionMgr.getSelection().contains(doc.getModelId());
    }

    private static final String TTAG = "TouchInputDelegate";
    private final class TouchInputDelegate {

        boolean onDown(T event) {
            if (VERBOSE) Log.v(TTAG, "Delegated onDown event.");
            return false;
        }

        // Don't consume so the RecyclerView will get the event and will get touch-based scrolling
        boolean onScroll(T event) {
            if (VERBOSE) Log.v(TTAG, "Delegated onScroll event.");
            return false;
        }

        boolean onSingleTapUp(T event) {
            if (VERBOSE) Log.v(TTAG, "Delegated onSingleTapUp event.");
            if (!event.isOverModelItem()) {
                if (DEBUG) Log.d(TTAG, "Tap not associated w/ model item. Clearing selection.");
                mSelectionMgr.clearSelection();
                return false;
            }

            DocumentDetails doc = event.getDocumentDetails();
            if (mSelectionMgr.hasSelection()) {
                if (isRangeExtension(event)) {
                    extendSelectionRange(doc);
                } else {
                    selectDocument(doc);
                }
                return true;
            }

            // Touch events select if they occur in the selection hotspot,
            // otherwise they activate.
            return doc.isInSelectionHotspot(event)
                    ? selectDocument(doc)
                    : mActions.openDocument(doc, ActionHandler.VIEW_TYPE_PREVIEW,
                            ActionHandler.VIEW_TYPE_REGULAR);
        }

        boolean onSingleTapConfirmed(T event) {
            if (VERBOSE) Log.v(TTAG, "Delegated onSingleTapConfirmed event.");
            return false;
        }

        boolean onDoubleTap(T event) {
            if (VERBOSE) Log.v(TTAG, "Delegated onDoubleTap event.");
            return false;
        }

        final void onLongPress(T event) {
            if (VERBOSE) Log.v(TTAG, "Delegated onLongPress event.");
            if (!event.isOverModelItem()) {
                if (DEBUG) Log.d(TTAG, "Ignoring LongPress on non-model-backed item.");
                return;
            }

            DocumentDetails doc = event.getDocumentDetails();
            if (isRangeExtension(event)) {
                extendSelectionRange(doc);
            } else {
                if (!mSelectionMgr.getSelection().contains(doc.getModelId())) {
                    selectDocument(doc);
                    // If we cannot select it, we didn't apply anchoring - therefore should not
                    // start gesture selection
                    if (mSelectable.test(doc)) {
                        mGestureSelectHandler.accept(event);
                    }
                } else {
                    // We only initiate drag and drop on long press for touch to allow regular
                    // touch-based scrolling
                    mTouchDragListener.accept(event);
                }
            }
        }
    }

    private static final String MTAG = "MouseInputDelegate";
    private final class MouseInputDelegate {
        // The event has been handled in onSingleTapUp
        private boolean mHandledTapUp;
        // true when the previous event has consumed a right click motion event
        private boolean mHandledOnDown;

        boolean onDown(T event) {
            if (VERBOSE) Log.v(MTAG, "Delegated onDown event.");
            if (event.isSecondaryButtonPressed()
                    || (event.isAltKeyDown() && event.isPrimaryButtonPressed())) {
                mHandledOnDown = true;
                return onRightClick(event);
            }

            return false;
        }

        // Don't scroll content window in response to mouse drag
        boolean onScroll(T event) {
            if (VERBOSE) Log.v(MTAG, "Delegated onScroll event.");
            // If it's two-finger trackpad scrolling, we want to scroll
            return !event.isTouchpadScroll();
        }

        boolean onSingleTapUp(T event) {
            if (VERBOSE) Log.v(MTAG, "Delegated onSingleTapUp event.");

            // See b/27377794. Since we don't get a button state back from UP events, we have to
            // explicitly save this state to know whether something was previously handled by
            // DOWN events or not.
            if (mHandledOnDown) {
                if (VERBOSE) Log.v(MTAG, "Ignoring onSingleTapUp, previously handled in onDown.");
                mHandledOnDown = false;
                return false;
            }

            if (!event.isOverModelItem()) {
                if (DEBUG) Log.d(MTAG, "Tap not associated w/ model item. Clearing selection.");
                mSelectionMgr.clearSelection();
                return false;
            }

            if (event.isTertiaryButtonPressed()) {
                if (DEBUG) Log.d(MTAG, "Ignoring middle click");
                return false;
            }

            DocumentDetails doc = event.getDocumentDetails();
            if (mSelectionMgr.hasSelection()) {
                if (isRangeExtension(event)) {
                    extendSelectionRange(doc);
                } else {
                    if (shouldClearSelection(event, doc)) {
                        mSelectionMgr.clearSelection();
                    }
                    selectDocument(doc);
                }
                mHandledTapUp = true;
                return true;
            }

            return false;
        }

        boolean onSingleTapConfirmed(T event) {
            if (VERBOSE) Log.v(MTAG, "Delegated onSingleTapConfirmed event.");
            if (mHandledTapUp) {
                if (VERBOSE) Log.v(MTAG, "Ignoring onSingleTapConfirmed, previously handled in onSingleTapUp.");
                mHandledTapUp = false;
                return false;
            }

            if (mSelectionMgr.hasSelection()) {
                return false;  // should have been handled by onSingleTapUp.
            }

            if (!event.isOverItem()) {
                if (DEBUG) Log.d(MTAG, "Ignoring Confirmed Tap on non-item.");
                return false;
            }

            if (event.isTertiaryButtonPressed()) {
                if (DEBUG) Log.d(MTAG, "Ignoring middle click");
                return false;
            }

            @Nullable DocumentDetails doc = event.getDocumentDetails();
            if (doc == null || !doc.hasModelId()) {
                Log.w(MTAG, "Ignoring Confirmed Tap. No document details associated w/ event.");
                return false;
            }

            if (mFocusHandler.hasFocusedItem() && event.isShiftKeyDown()) {
                mSelectionMgr.formNewSelectionRange(mFocusHandler.getFocusPosition(),
                        doc.getAdapterPosition());
                return true;
            } else {
                return selectDocument(doc);
            }
        }

        boolean onDoubleTap(T event) {
            if (VERBOSE) Log.v(MTAG, "Delegated onDoubleTap event.");
            mHandledTapUp = false;

            if (!event.isOverModelItem()) {
                if (DEBUG) Log.d(MTAG, "Ignoring DoubleTap on non-model-backed item.");
                return false;
            }

            if (event.isTertiaryButtonPressed()) {
                if (DEBUG) Log.d(MTAG, "Ignoring middle click");
                return false;
            }

            DocumentDetails doc = event.getDocumentDetails();
            return mActions.openDocument(doc, ActionHandler.VIEW_TYPE_REGULAR,
                    ActionHandler.VIEW_TYPE_PREVIEW);
        }

        final void onLongPress(T event) {
            if (VERBOSE) Log.v(MTAG, "Delegated onLongPress event.");
            return;
        }

        private boolean onRightClick(T event) {
            if (VERBOSE) Log.v(MTAG, "Delegated onRightClick event.");
            if (event.isOverModelItem()) {
                DocumentDetails doc = event.getDocumentDetails();
                if (!mSelectionMgr.getSelection().contains(doc.getModelId())) {
                    mSelectionMgr.replaceSelection(Collections.singleton(doc.getModelId()));
                    mSelectionMgr.setSelectionRangeBegin(doc.getAdapterPosition());
                }
            }

            // We always delegate final handling of the event,
            // since the handler might want to show a context menu
            // in an empty area or some other weirdo view.
            return mContextMenuClickHandler.accept(event);
        }
    }

    private final class KeyInputHandler {
        // TODO: Refactor FocusManager to depend only on DocumentDetails so we can eliminate
        // difficult to test dependency on DocumentHolder.

        boolean onKey(@Nullable DocumentHolder doc, int keyCode, KeyEvent event) {
            // Only handle key-down events. This is simpler, consistent with most other UIs, and
            // enables the handling of repeated key events from holding down a key.
            if (event.getAction() != KeyEvent.ACTION_DOWN) {
                return false;
            }

            // Ignore tab key events.  Those should be handled by the top-level key handler.
            if (keyCode == KeyEvent.KEYCODE_TAB) {
                return false;
            }

            // Ignore events sent to Addon Holders.
            if (doc != null) {
                int itemType = doc.getItemViewType();
                if (itemType == DocumentsAdapter.ITEM_TYPE_HEADER_MESSAGE
                        || itemType == DocumentsAdapter.ITEM_TYPE_INFLATED_MESSAGE
                        || itemType == DocumentsAdapter.ITEM_TYPE_SECTION_BREAK) {
                    return false;
                }
            }

            if (mFocusHandler.handleKey(doc, keyCode, event)) {
                // Handle range selection adjustments. Extending the selection will adjust the
                // bounds of the in-progress range selection. Each time an unshifted navigation
                // event is received, the range selection is restarted.
                if (shouldExtendSelection(doc, event)) {
                    if (!mSelectionMgr.isRangeSelectionActive()) {
                        // Start a range selection if one isn't active
                        mSelectionMgr.startRangeSelection(doc.getAdapterPosition());
                    }
                    mSelectionMgr.snapRangeSelection(mFocusHandler.getFocusPosition());
                } else {
                    mSelectionMgr.endRangeSelection();
                    mSelectionMgr.clearSelection();
                }
                return true;
            }

            // Handle enter key events
            switch (keyCode) {
                case KeyEvent.KEYCODE_ENTER:
                    if (event.isShiftPressed()) {
                        selectDocument(doc);
                    }
                    // For non-shifted enter keypresses, fall through.
                case KeyEvent.KEYCODE_DPAD_CENTER:
                case KeyEvent.KEYCODE_BUTTON_A:
                    return mActions.openDocument(doc, ActionHandler.VIEW_TYPE_REGULAR,
                            ActionHandler.VIEW_TYPE_PREVIEW);
                case KeyEvent.KEYCODE_SPACE:
                    return mActions.openDocument(doc, ActionHandler.VIEW_TYPE_PREVIEW,
                            ActionHandler.VIEW_TYPE_NONE);
            }

            return false;
        }

        private boolean shouldExtendSelection(DocumentDetails doc, KeyEvent event) {
            if (!Events.isNavigationKeyCode(event.getKeyCode()) || !event.isShiftPressed()) {
                return false;
            }

            return mSelectable.test(doc);
        }
    }
}
