/*
 * Copyright (C) 2015 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 android.widget.cts;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.cts.util.KeyEventUtil;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
import android.widget.ListPopupWindow;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.cts.util.ViewTestUtils;

import static org.mockito.Mockito.*;

@SmallTest
public class ListPopupWindowTest extends
        ActivityInstrumentationTestCase2<ListPopupWindowCtsActivity> {
    private Instrumentation mInstrumentation;
    private Activity mActivity;
    private KeyEventUtil mKeyEventUtil;
    private Builder mPopupWindowBuilder;

    /** The list popup window. */
    private ListPopupWindow mPopupWindow;

    private AdapterView.OnItemClickListener mItemClickListener;

    /**
     * Item click listener that dismisses our <code>ListPopupWindow</code> when any item
     * is clicked. Note that this needs to be a separate class that is also protected (not
     * private) so that Mockito can "spy" on it.
     */
    protected class PopupItemClickListener implements AdapterView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            mPopupWindow.dismiss();
        }
    }

    /**
     * Instantiates a new popup window test.
     */
    public ListPopupWindowTest() {
        super(ListPopupWindowCtsActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mInstrumentation = getInstrumentation();
        mActivity = getActivity();
        mItemClickListener = new PopupItemClickListener();
        mKeyEventUtil = new KeyEventUtil(mInstrumentation);
    }

    @Override
    protected void tearDown() throws Exception {
        if ((mPopupWindowBuilder != null) && (mPopupWindow != null)) {
            mPopupWindowBuilder.dismiss();
        }

        super.tearDown();
    }

    public void testConstructor() {
        new ListPopupWindow(mActivity);

        new ListPopupWindow(mActivity, null);

        new ListPopupWindow(mActivity, null, android.R.attr.popupWindowStyle);

        new ListPopupWindow(mActivity, null, 0, android.R.style.Widget_Material_ListPopupWindow);
    }

    public void testNoDefaultVisibility() {
        mPopupWindow = new ListPopupWindow(mActivity);
        assertFalse(mPopupWindow.isShowing());
    }

    public void testAccessBackground() {
        mPopupWindowBuilder = new Builder();
        mPopupWindowBuilder.show();

        Drawable drawable = new ColorDrawable();
        mPopupWindow.setBackgroundDrawable(drawable);
        assertSame(drawable, mPopupWindow.getBackground());

        mPopupWindow.setBackgroundDrawable(null);
        assertNull(mPopupWindow.getBackground());
    }

    public void testAccessAnimationStyle() {
        mPopupWindowBuilder = new Builder();
        mPopupWindowBuilder.show();
        assertEquals(0, mPopupWindow.getAnimationStyle());

        mPopupWindow.setAnimationStyle(android.R.style.Animation_Toast);
        assertEquals(android.R.style.Animation_Toast, mPopupWindow.getAnimationStyle());

        // abnormal values
        mPopupWindow.setAnimationStyle(-100);
        assertEquals(-100, mPopupWindow.getAnimationStyle());
    }

    public void testAccessHeight() {
        mPopupWindowBuilder = new Builder();
        mPopupWindowBuilder.show();

        assertEquals(WindowManager.LayoutParams.WRAP_CONTENT, mPopupWindow.getHeight());

        int height = getDisplay().getHeight() / 2;
        mPopupWindow.setHeight(height);
        assertEquals(height, mPopupWindow.getHeight());

        height = getDisplay().getHeight();
        mPopupWindow.setHeight(height);
        assertEquals(height, mPopupWindow.getHeight());

        mPopupWindow.setHeight(0);
        assertEquals(0, mPopupWindow.getHeight());

        height = getDisplay().getHeight() * 2;
        mPopupWindow.setHeight(height);
        assertEquals(height, mPopupWindow.getHeight());

        height = -getDisplay().getHeight() / 2;
        mPopupWindow.setHeight(height);
        assertEquals(height, mPopupWindow.getHeight());
    }

    /**
     * Gets the display.
     *
     * @return the display
     */
    private Display getDisplay() {
        WindowManager wm = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
        return wm.getDefaultDisplay();
    }

    public void testAccessWidth() {
        mPopupWindowBuilder = new Builder().ignoreContentWidth();
        mPopupWindowBuilder.show();

        assertEquals(WindowManager.LayoutParams.WRAP_CONTENT, mPopupWindow.getWidth());

        int width = getDisplay().getWidth() / 2;
        mPopupWindow.setWidth(width);
        assertEquals(width, mPopupWindow.getWidth());

        width = getDisplay().getWidth();
        mPopupWindow.setWidth(width);
        assertEquals(width, mPopupWindow.getWidth());

        mPopupWindow.setWidth(0);
        assertEquals(0, mPopupWindow.getWidth());

        width = getDisplay().getWidth() * 2;
        mPopupWindow.setWidth(width);
        assertEquals(width, mPopupWindow.getWidth());

        width = - getDisplay().getWidth() / 2;
        mPopupWindow.setWidth(width);
        assertEquals(width, mPopupWindow.getWidth());
    }

    private void verifyAnchoring(int horizontalOffset, int verticalOffset, int gravity) {
        final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
        final ListView listView = mPopupWindow.getListView();
        int[] anchorXY = new int[2];
        int[] listViewOnScreenXY = new int[2];
        int[] listViewInWindowXY = new int[2];

        assertTrue(mPopupWindow.isShowing());
        assertEquals(upperAnchor, mPopupWindow.getAnchorView());

        listView.getLocationOnScreen(listViewOnScreenXY);
        upperAnchor.getLocationOnScreen(anchorXY);
        listView.getLocationInWindow(listViewInWindowXY);

        int expectedListViewOnScreenX = anchorXY[0] + listViewInWindowXY[0] + horizontalOffset;
        final int absoluteGravity =
                Gravity.getAbsoluteGravity(gravity, upperAnchor.getLayoutDirection());
        if (absoluteGravity == Gravity.RIGHT) {
            expectedListViewOnScreenX -= (listView.getWidth() - upperAnchor.getWidth());
        }
        int expectedListViewOnScreenY = anchorXY[1] + listViewInWindowXY[1]
                + upperAnchor.getHeight() + verticalOffset;
        assertEquals(expectedListViewOnScreenX, listViewOnScreenXY[0]);
        assertEquals(expectedListViewOnScreenY, listViewOnScreenXY[1]);
    }

    public void testAnchoring() {
        mPopupWindowBuilder = new Builder();
        mPopupWindowBuilder.show();

        assertEquals(0, mPopupWindow.getHorizontalOffset());
        assertEquals(0, mPopupWindow.getVerticalOffset());

        verifyAnchoring(0, 0, Gravity.NO_GRAVITY);
    }

    public void testAnchoringWithHorizontalOffset() {
        mPopupWindowBuilder = new Builder().withHorizontalOffset(50);
        mPopupWindowBuilder.show();

        assertEquals(50, mPopupWindow.getHorizontalOffset());
        assertEquals(0, mPopupWindow.getVerticalOffset());

        verifyAnchoring(50, 0, Gravity.NO_GRAVITY);
    }

    public void testAnchoringWithVerticalOffset() {
        mPopupWindowBuilder = new Builder().withVerticalOffset(60);
        mPopupWindowBuilder.show();

        assertEquals(0, mPopupWindow.getHorizontalOffset());
        assertEquals(60, mPopupWindow.getVerticalOffset());

        verifyAnchoring(0, 60, Gravity.NO_GRAVITY);
    }

    public void testAnchoringWithRightGravity() {
        mPopupWindowBuilder = new Builder().withDropDownGravity(Gravity.RIGHT);
        mPopupWindowBuilder.show();

        assertEquals(0, mPopupWindow.getHorizontalOffset());
        assertEquals(0, mPopupWindow.getVerticalOffset());

        verifyAnchoring(0, 0, Gravity.RIGHT);
    }

    public void testAnchoringWithEndGravity() {
        mPopupWindowBuilder = new Builder().withDropDownGravity(Gravity.END);
        mPopupWindowBuilder.show();

        assertEquals(0, mPopupWindow.getHorizontalOffset());
        assertEquals(0, mPopupWindow.getVerticalOffset());

        verifyAnchoring(0, 0, Gravity.END);
    }

    public void testSetWindowLayoutType() {
        mPopupWindowBuilder = new Builder().withWindowLayoutType(
                WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
        mPopupWindowBuilder.show();
        assertTrue(mPopupWindow.isShowing());

        WindowManager.LayoutParams p = (WindowManager.LayoutParams)
                mPopupWindow.getListView().getRootView().getLayoutParams();
        assertEquals(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, p.type);
    }

    public void testDismiss() {
        mPopupWindowBuilder = new Builder();
        mPopupWindowBuilder.show();
        assertTrue(mPopupWindow.isShowing());

        mPopupWindowBuilder.dismiss();
        assertFalse(mPopupWindow.isShowing());

        mPopupWindowBuilder.dismiss();
        assertFalse(mPopupWindow.isShowing());
    }

    public void testSetOnDismissListener() {
        mPopupWindowBuilder = new Builder().withDismissListener();
        mPopupWindowBuilder.show();
        mPopupWindowBuilder.dismiss();
        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();

        mPopupWindowBuilder.showAgain();
        mPopupWindowBuilder.dismiss();
        verify(mPopupWindowBuilder.mOnDismissListener, times(2)).onDismiss();

        mPopupWindow.setOnDismissListener(null);
        mPopupWindowBuilder.showAgain();
        mPopupWindowBuilder.dismiss();
        // Since we've reset the listener to null, we are not expecting any more interactions
        // on the previously registered listener.
        verifyNoMoreInteractions(mPopupWindowBuilder.mOnDismissListener);
    }

    public void testAccessInputMethodMode() {
        mPopupWindowBuilder = new Builder().withDismissListener();
        mPopupWindowBuilder.show();

        assertEquals(PopupWindow.INPUT_METHOD_NEEDED, mPopupWindow.getInputMethodMode());
        assertFalse(mPopupWindow.isInputMethodNotNeeded());

        mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_FROM_FOCUSABLE);
        assertEquals(PopupWindow.INPUT_METHOD_FROM_FOCUSABLE, mPopupWindow.getInputMethodMode());
        assertFalse(mPopupWindow.isInputMethodNotNeeded());

        mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
        assertEquals(PopupWindow.INPUT_METHOD_NEEDED, mPopupWindow.getInputMethodMode());
        assertFalse(mPopupWindow.isInputMethodNotNeeded());

        mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
        assertEquals(PopupWindow.INPUT_METHOD_NOT_NEEDED, mPopupWindow.getInputMethodMode());
        assertTrue(mPopupWindow.isInputMethodNotNeeded());

        mPopupWindow.setInputMethodMode(-1);
        assertEquals(-1, mPopupWindow.getInputMethodMode());
        assertFalse(mPopupWindow.isInputMethodNotNeeded());
    }

    public void testAccessSoftInputMethodMode() {
        mPopupWindowBuilder = new Builder().withDismissListener();
        mPopupWindowBuilder.show();

        mPopupWindow = new ListPopupWindow(mActivity);
        assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED,
                mPopupWindow.getSoftInputMode());

        mPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        assertEquals(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE,
                mPopupWindow.getSoftInputMode());

        mPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE,
                mPopupWindow.getSoftInputMode());
    }

    private void verifyDismissalViaTouch(boolean setupAsModal) throws Throwable {
        // Register a click listener on the top-level container
        final View mainContainer = mActivity.findViewById(R.id.main_container);
        View.OnClickListener mockContainerClickListener = mock(View.OnClickListener.class);
        mainContainer.setOnClickListener(mockContainerClickListener);

        // Configure a list popup window with requested modality
        mPopupWindowBuilder = new Builder().setModal(setupAsModal).withDismissListener();
        mPopupWindowBuilder.show();

        assertTrue("Popup window showing", mPopupWindow.isShowing());
        // Make sure that the modality of the popup window is set up correctly
        assertEquals("Popup window modality", setupAsModal, mPopupWindow.isModal());

        // Determine the location of the popup on the screen so that we can emulate
        // a tap outside of its bounds to dismiss it
        final int[] popupOnScreenXY = new int[2];
        final Rect rect = new Rect();
        mPopupWindow.getListView().getLocationOnScreen(popupOnScreenXY);
        mPopupWindow.getBackground().getPadding(rect);

        int emulatedTapX = popupOnScreenXY[0] - rect.left - 20;
        int emulatedTapY = popupOnScreenXY[1] + mPopupWindow.getListView().getHeight() +
                rect.top + rect.bottom + 20;

        // The logic below uses Instrumentation to emulate a tap outside the bounds of the
        // displayed list popup window. This tap is then treated by the framework to be "split" as
        // the ACTION_OUTSIDE for the popup itself, as well as DOWN / MOVE / UP for the underlying
        // view root if the popup is not modal.
        // It is not correct to emulate these two sequences separately in the test, as it
        // wouldn't emulate the user-facing interaction for this test. Note that usage
        // of Instrumentation is necessary here since Espresso's actions operate at the level
        // of view or data. Also, we don't want to use View.dispatchTouchEvent directly as
        // that would require emulation of two separate sequences as well.

        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();

        // Inject DOWN event
        long downTime = SystemClock.uptimeMillis();
        MotionEvent eventDown = MotionEvent.obtain(
                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
        instrumentation.sendPointerSync(eventDown);

        // Inject MOVE event
        long moveTime = SystemClock.uptimeMillis();
        MotionEvent eventMove = MotionEvent.obtain(
                moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
        instrumentation.sendPointerSync(eventMove);

        // Inject UP event
        long upTime = SystemClock.uptimeMillis();
        MotionEvent eventUp = MotionEvent.obtain(
                upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
        instrumentation.sendPointerSync(eventUp);

        // Wait for the system to process all events in the queue
        instrumentation.waitForIdleSync();

        // At this point our popup should not be showing and should have notified its
        // dismiss listener
        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
        assertFalse("Popup window not showing after outside click", mPopupWindow.isShowing());

        // Also test that the click outside the popup bounds has been "delivered" to the main
        // container only if the popup is not modal
        verify(mockContainerClickListener, times(setupAsModal ? 0 : 1)).onClick(mainContainer);
    }

    public void testDismissalOutsideNonModal() throws Throwable {
        verifyDismissalViaTouch(false);
    }

    public void testDismissalOutsideModal() throws Throwable {
        verifyDismissalViaTouch(true);
    }

    public void testItemClicks() throws Throwable {
        mPopupWindowBuilder = new Builder().withItemClickListener().withDismissListener();
        mPopupWindowBuilder.show();

        runTestOnUiThread(() -> mPopupWindow.performItemClick(2));
        mInstrumentation.waitForIdleSync();

        verify(mPopupWindowBuilder.mOnItemClickListener, times(1)).onItemClick(
                any(AdapterView.class), any(View.class), eq(2), eq(2L));
        // Also verify that the popup window has been dismissed
        assertFalse(mPopupWindow.isShowing());
        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();

        mPopupWindowBuilder.showAgain();
        runTestOnUiThread(() -> mPopupWindow.getListView().performItemClick(null, 1, 1));
        mInstrumentation.waitForIdleSync();

        verify(mPopupWindowBuilder.mOnItemClickListener, times(1)).onItemClick(
                any(AdapterView.class), any(View.class), eq(1), eq(1L));
        // Also verify that the popup window has been dismissed
        assertFalse(mPopupWindow.isShowing());
        verify(mPopupWindowBuilder.mOnDismissListener, times(2)).onDismiss();

        // Finally verify that our item click listener has only been called twice
        verifyNoMoreInteractions(mPopupWindowBuilder.mOnItemClickListener);
    }

    public void testPromptViewAbove() throws Throwable {
        final View promptView = LayoutInflater.from(mActivity).inflate(
                R.layout.popupwindow_prompt, null);
        mPopupWindowBuilder = new Builder().withPrompt(
                promptView, ListPopupWindow.POSITION_PROMPT_ABOVE);
        mPopupWindowBuilder.show();

        // Verify that our prompt is displayed on the screen and is above the first list item
        assertTrue(promptView.isAttachedToWindow());
        assertTrue(promptView.isShown());
        assertEquals(ListPopupWindow.POSITION_PROMPT_ABOVE, mPopupWindow.getPromptPosition());

        final int[] promptViewOnScreenXY = new int[2];
        promptView.getLocationOnScreen(promptViewOnScreenXY);

        final ListView listView = mPopupWindow.getListView();
        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, listView, null);

        final View firstListChild = listView.getChildAt(0);
        final int[] firstChildOnScreenXY = new int[2];
        firstListChild.getLocationOnScreen(firstChildOnScreenXY);

        assertTrue(promptViewOnScreenXY[1] + promptView.getHeight() <= firstChildOnScreenXY[1]);
    }

    public void testPromptViewBelow() throws Throwable {
        final View promptView = LayoutInflater.from(mActivity).inflate(
                R.layout.popupwindow_prompt, null);
        mPopupWindowBuilder = new Builder().withPrompt(
                promptView, ListPopupWindow.POSITION_PROMPT_BELOW);
        mPopupWindowBuilder.show();

        // Verify that our prompt is displayed on the screen and is below the last list item
        assertTrue(promptView.isAttachedToWindow());
        assertTrue(promptView.isShown());
        assertEquals(ListPopupWindow.POSITION_PROMPT_BELOW, mPopupWindow.getPromptPosition());

        final ListView listView = mPopupWindow.getListView();
        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, listView, null);

        final int[] promptViewOnScreenXY = new int[2];
        promptView.getLocationOnScreen(promptViewOnScreenXY);

        final View lastListChild = listView.getChildAt(listView.getChildCount() - 1);
        final int[] lastChildOnScreenXY = new int[2];
        lastListChild.getLocationOnScreen(lastChildOnScreenXY);

        // The child is above the prompt. They may overlap, as in the case
        // when the list items do not all fit on screen, but this is still
        // correct.
        assertTrue(lastChildOnScreenXY[1] <= promptViewOnScreenXY[1]);
    }

    @Presubmit
    public void testAccessSelection() throws Throwable {
        mPopupWindowBuilder = new Builder().withItemSelectedListener();
        mPopupWindowBuilder.show();

        final ListView listView = mPopupWindow.getListView();

        // Select an item
        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, listView,
                () -> mPopupWindow.setSelection(1));

        // And verify the current selection state + selection listener invocation
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(1), eq(1L));
        assertEquals(1, mPopupWindow.getSelectedItemId());
        assertEquals(1, mPopupWindow.getSelectedItemPosition());
        assertEquals("Bob", mPopupWindow.getSelectedItem());
        View selectedView = mPopupWindow.getSelectedView();
        assertNotNull(selectedView);
        assertEquals("Bob",
                ((TextView) selectedView.findViewById(android.R.id.text1)).getText());

        // Select another item
        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, listView,
                () -> mPopupWindow.setSelection(3));

        // And verify the new selection state + selection listener invocation
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(3), eq(3L));
        assertEquals(3, mPopupWindow.getSelectedItemId());
        assertEquals(3, mPopupWindow.getSelectedItemPosition());
        assertEquals("Deirdre", mPopupWindow.getSelectedItem());
        selectedView = mPopupWindow.getSelectedView();
        assertNotNull(selectedView);
        assertEquals("Deirdre",
                ((TextView) selectedView.findViewById(android.R.id.text1)).getText());

        // Clear selection
        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, listView,
                () -> mPopupWindow.clearListSelection());

        // And verify empty selection state + no more selection listener invocation
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onNothingSelected(
                any(AdapterView.class));
        assertEquals(AdapterView.INVALID_ROW_ID, mPopupWindow.getSelectedItemId());
        assertEquals(AdapterView.INVALID_POSITION, mPopupWindow.getSelectedItemPosition());
        assertEquals(null, mPopupWindow.getSelectedItem());
        assertEquals(null, mPopupWindow.getSelectedView());
        verifyNoMoreInteractions(mPopupWindowBuilder.mOnItemSelectedListener);
    }

    public void testNoDefaultDismissalWithBackButton() throws Throwable {
        mPopupWindowBuilder = new Builder().withDismissListener();
        mPopupWindowBuilder.show();

        // Send BACK key event. As we don't have any custom code that dismisses ListPopupWindow,
        // and ListPopupWindow doesn't track that system-level key event on its own, ListPopupWindow
        // should stay visible
        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
        verify(mPopupWindowBuilder.mOnDismissListener, never()).onDismiss();
        assertTrue(mPopupWindow.isShowing());
    }

    public void testCustomDismissalWithBackButton() throws Throwable {
        mPopupWindowBuilder = new Builder().withAnchor(R.id.anchor_upper_left)
                .withDismissListener();
        mPopupWindowBuilder.show();

        // "Point" our custom extension of EditText to our ListPopupWindow
        final MockViewForListPopupWindow anchor =
                (MockViewForListPopupWindow) mPopupWindow.getAnchorView();
        anchor.wireTo(mPopupWindow);
        // Request focus on our EditText
        runTestOnUiThread(() -> anchor.requestFocus());
        mInstrumentation.waitForIdleSync();
        assertTrue(anchor.isFocused());

        // Send BACK key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyPreIme, the end result should be the dismissal of the
        // ListPopupWindow
        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
        assertFalse(mPopupWindow.isShowing());
    }

    public void testListSelectionWithDPad() throws Throwable {
        mPopupWindowBuilder = new Builder().withAnchor(R.id.anchor_upper_left)
                .withDismissListener().withItemSelectedListener();
        mPopupWindowBuilder.show();

        final View root = mPopupWindow.getListView().getRootView();

        // "Point" our custom extension of EditText to our ListPopupWindow
        final MockViewForListPopupWindow anchor =
                (MockViewForListPopupWindow) mPopupWindow.getAnchorView();
        anchor.wireTo(mPopupWindow);
        // Request focus on our EditText
        runTestOnUiThread(() -> anchor.requestFocus());
        mInstrumentation.waitForIdleSync();
        assertTrue(anchor.isFocused());

        // Select entry #1 in the popup list
        final ListView listView = mPopupWindow.getListView();
        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, listView,
                () -> mPopupWindow.setSelection(1));
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(1), eq(1L));

        // Send DPAD_DOWN key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
        // down one row
        mKeyEventUtil.sendKeyDownUp(listView, KeyEvent.KEYCODE_DPAD_DOWN);
        mInstrumentation.waitForIdleSync();

        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, root, null);

        // At this point we expect that item #2 was selected
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(2), eq(2L));

        // Send a DPAD_UP key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
        // up one row
        mKeyEventUtil.sendKeyDownUp(listView, KeyEvent.KEYCODE_DPAD_UP);
        mInstrumentation.waitForIdleSync();

        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, root, null);

        // At this point we expect that item #1 was selected
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(2)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(1), eq(1L));

        // Send one more DPAD_UP key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
        // up one more row
        mKeyEventUtil.sendKeyDownUp(listView, KeyEvent.KEYCODE_DPAD_UP);
        mInstrumentation.waitForIdleSync();

        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, root, null);

        // At this point we expect that item #0 was selected
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(0), eq(0L));

        // Send ENTER key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be dismissal of
        // the popup window
        mKeyEventUtil.sendKeyDownUp(listView, KeyEvent.KEYCODE_ENTER);
        mInstrumentation.waitForIdleSync();

        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
        assertFalse(mPopupWindow.isShowing());

        verifyNoMoreInteractions(mPopupWindowBuilder.mOnItemSelectedListener);
        verifyNoMoreInteractions(mPopupWindowBuilder.mOnDismissListener);
    }

    /**
     * Emulates a drag-down gestures by injecting ACTION events with {@link Instrumentation}.
     */
    private void emulateDragDownGesture(int emulatedX, int emulatedStartY, int swipeAmount) {
        // The logic below uses Instrumentation to emulate a swipe / drag gesture to bring up
        // the popup content.

        // Inject DOWN event
        long downTime = SystemClock.uptimeMillis();
        MotionEvent eventDown = MotionEvent.obtain(
                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedX, emulatedStartY, 1);
        mInstrumentation.sendPointerSync(eventDown);

        // Inject a sequence of MOVE events that emulate a "swipe down" gesture
        for (int i = 0; i < 10; i++) {
            long moveTime = SystemClock.uptimeMillis();
            final int moveY = emulatedStartY + swipeAmount * i / 10;
            MotionEvent eventMove = MotionEvent.obtain(
                    moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedX, moveY, 1);
            mInstrumentation.sendPointerSync(eventMove);
            // sleep for a bit to emulate a 200ms swipe
            SystemClock.sleep(20);
        }

        // Inject UP event
        long upTime = SystemClock.uptimeMillis();
        MotionEvent eventUp = MotionEvent.obtain(
                upTime, upTime, MotionEvent.ACTION_UP, emulatedX, emulatedStartY + swipeAmount, 1);
        mInstrumentation.sendPointerSync(eventUp);

        // Wait for the system to process all events in the queue
        mInstrumentation.waitForIdleSync();
    }

    public void testCreateOnDragListener() throws Throwable {
        // In this test we want precise control over the height of the popup content since
        // we need to know by how much to swipe down to end the emulated gesture over the
        // specific item in the popup. This is why we're using a popup style that removes
        // all decoration around the popup content, as well as our own row layout with known
        // height.
        mPopupWindowBuilder = new Builder()
                .withPopupStyleAttr(R.style.PopupEmptyStyle)
                .withContentRowLayoutId(R.layout.popup_window_item)
                .withItemClickListener().withDismissListener();

        // Configure ListPopupWindow without showing it
        mPopupWindowBuilder.configure();

        // Get the anchor view and configure it with ListPopupWindow's drag-to-open listener
        final View anchor = mActivity.findViewById(mPopupWindowBuilder.mAnchorId);
        View.OnTouchListener dragListener = mPopupWindow.createDragToOpenListener(anchor);
        anchor.setOnTouchListener(dragListener);
        // And also configure it to show the popup window on click
        anchor.setOnClickListener((View view) -> mPopupWindow.show());

        // Get the height of a row item in our popup window
        final int popupRowHeight = mActivity.getResources().getDimensionPixelSize(
                R.dimen.popup_row_height);

        final int[] anchorOnScreenXY = new int[2];
        anchor.getLocationOnScreen(anchorOnScreenXY);

        // Compute the start coordinates of a downward swipe and the amount of swipe. We'll
        // be swiping by twice the row height. That, combined with the swipe originating in the
        // center of the anchor should result in clicking the second row in the popup.
        int emulatedX = anchorOnScreenXY[0] + anchor.getWidth() / 2;
        int emulatedStartY = anchorOnScreenXY[1] + anchor.getHeight() / 2;
        int swipeAmount = 2 * popupRowHeight;

        // Emulate drag-down gesture with a sequence of motion events
        emulateDragDownGesture(emulatedX, emulatedStartY, swipeAmount);

        // We expect the swipe / drag gesture to result in clicking the second item in our list.
        verify(mPopupWindowBuilder.mOnItemClickListener, times(1)).onItemClick(
                any(AdapterView.class), any(View.class), eq(1), eq(1L));
        // Since our item click listener calls dismiss() on the popup, we expect the popup to not
        // be showing
        assertFalse(mPopupWindow.isShowing());
        // At this point our popup should have notified its dismiss listener
        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
    }

    /**
     * Inner helper class to configure an instance of <code>ListPopupWindow</code> for the
     * specific test. The main reason for its existence is that once a popup window is shown
     * with the show() method, most of its configuration APIs are no-ops. This means that
     * we can't add logic that is specific to a certain test (such as dismissing a non-modal
     * popup window) once it's shown and we have a reference to a displayed ListPopupWindow.
     */
    public class Builder {
        private boolean mIsModal;
        private boolean mHasDismissListener;
        private boolean mHasItemClickListener;
        private boolean mHasItemSelectedListener;
        private boolean mIgnoreContentWidth;
        private int mHorizontalOffset;
        private int mVerticalOffset;
        private int mDropDownGravity;
        private int mAnchorId = R.id.anchor_upper;
        private int mContentRowLayoutId = android.R.layout.simple_list_item_1;

        private boolean mHasWindowLayoutType;
        private int mWindowLayoutType;

        private boolean mUseCustomPopupStyle;
        private int mPopupStyleAttr;

        private View mPromptView;
        private int mPromptPosition;

        private AdapterView.OnItemClickListener mOnItemClickListener;
        private AdapterView.OnItemSelectedListener mOnItemSelectedListener;
        private PopupWindow.OnDismissListener mOnDismissListener;

        public Builder() {
        }

        public Builder withAnchor(int anchorId) {
            mAnchorId = anchorId;
            return this;
        }

        public Builder withContentRowLayoutId(int contentRowLayoutId) {
            mContentRowLayoutId = contentRowLayoutId;
            return this;
        }

        public Builder withPopupStyleAttr(int popupStyleAttr) {
            mUseCustomPopupStyle = true;
            mPopupStyleAttr = popupStyleAttr;
            return this;
        }

        public Builder ignoreContentWidth() {
            mIgnoreContentWidth = true;
            return this;
        }

        public Builder setModal(boolean isModal) {
            mIsModal = isModal;
            return this;
        }

        public Builder withItemClickListener() {
            mHasItemClickListener = true;
            return this;
        }

        public Builder withItemSelectedListener() {
            mHasItemSelectedListener = true;
            return this;
        }

        public Builder withDismissListener() {
            mHasDismissListener = true;
            return this;
        }

        public Builder withWindowLayoutType(int windowLayoutType) {
            mHasWindowLayoutType = true;
            mWindowLayoutType = windowLayoutType;
            return this;
        }

        public Builder withHorizontalOffset(int horizontalOffset) {
            mHorizontalOffset = horizontalOffset;
            return this;
        }

        public Builder withVerticalOffset(int verticalOffset) {
            mVerticalOffset = verticalOffset;
            return this;
        }

        public Builder withDropDownGravity(int dropDownGravity) {
            mDropDownGravity = dropDownGravity;
            return this;
        }

        public Builder withPrompt(View promptView, int promptPosition) {
            mPromptView = promptView;
            mPromptPosition = promptPosition;
            return this;
        }

        private int getContentWidth(ListAdapter listAdapter, Drawable background) {
            if (listAdapter == null) {
                return 0;
            }

            int width = 0;
            View itemView = null;
            int itemType = 0;

            for (int i = 0; i < listAdapter.getCount(); i++) {
                final int positionType = listAdapter.getItemViewType(i);
                if (positionType != itemType) {
                    itemType = positionType;
                    itemView = null;
                }
                itemView = listAdapter.getView(i, itemView, null);
                if (itemView.getLayoutParams() == null) {
                    itemView.setLayoutParams(new ViewGroup.LayoutParams(
                            ViewGroup.LayoutParams.WRAP_CONTENT,
                            ViewGroup.LayoutParams.WRAP_CONTENT));
                }
                itemView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
                width = Math.max(width, itemView.getMeasuredWidth());
            }

            // Add background padding to measured width
            if (background != null) {
                final Rect rect = new Rect();
                background.getPadding(rect);
                width += rect.left + rect.right;
            }

            return width;
        }

        private void configure() {
            if (mUseCustomPopupStyle) {
                mPopupWindow = new ListPopupWindow(mActivity, null, mPopupStyleAttr, 0);
            } else {
                mPopupWindow = new ListPopupWindow(mActivity);
            }
            final String[] POPUP_CONTENT =
                    new String[]{"Alice", "Bob", "Charlie", "Deirdre", "El"};
            final BaseAdapter listPopupAdapter = new BaseAdapter() {
                class ViewHolder {
                    private TextView title;
                }

                @Override
                public int getCount() {
                    return POPUP_CONTENT.length;
                }

                @Override
                public Object getItem(int position) {
                    return POPUP_CONTENT[position];
                }

                @Override
                public long getItemId(int position) {
                    return position;
                }

                @Override
                public View getView(int position, View convertView, ViewGroup parent) {
                    if (convertView == null) {
                        convertView = LayoutInflater.from(mActivity).inflate(
                                mContentRowLayoutId, parent, false);
                        ViewHolder viewHolder = new ViewHolder();
                        viewHolder.title = (TextView) convertView.findViewById(android.R.id.text1);
                        convertView.setTag(viewHolder);
                    }

                    ViewHolder viewHolder = (ViewHolder) convertView.getTag();
                    viewHolder.title.setText(POPUP_CONTENT[position]);
                    return convertView;
                }
            };

            mPopupWindow.setAdapter(listPopupAdapter);
            mPopupWindow.setAnchorView(mActivity.findViewById(mAnchorId));

            // The following mock listeners have to be set before the call to show() as
            // they are set on the internally constructed drop down.
            if (mHasItemClickListener) {
                // Wrap our item click listener with a Mockito spy
                mOnItemClickListener = spy(mItemClickListener);
                // Register that spy as the item click listener on the ListPopupWindow
                mPopupWindow.setOnItemClickListener(mOnItemClickListener);
                // And configure Mockito to call our original listener with onItemClick.
                // This way we can have both our item click listener running to dismiss the popup
                // window, and track the invocations of onItemClick with Mockito APIs.
                doCallRealMethod().when(mOnItemClickListener).onItemClick(
                        any(AdapterView.class), any(View.class), any(int.class), any(int.class));
            }

            if (mHasItemSelectedListener) {
                mOnItemSelectedListener = mock(AdapterView.OnItemSelectedListener.class);
                mPopupWindow.setOnItemSelectedListener(mOnItemSelectedListener);
                mPopupWindow.setListSelector(mActivity.getDrawable(R.drawable.red_fill));
            }

            if (mHasDismissListener) {
                mOnDismissListener = mock(PopupWindow.OnDismissListener.class);
                mPopupWindow.setOnDismissListener(mOnDismissListener);
            }

            mPopupWindow.setModal(mIsModal);
            if (mHasWindowLayoutType) {
                mPopupWindow.setWindowLayoutType(mWindowLayoutType);
            }

            if (!mIgnoreContentWidth) {
                mPopupWindow.setContentWidth(
                        getContentWidth(listPopupAdapter, mPopupWindow.getBackground()));
            }

            if (mHorizontalOffset != 0) {
                mPopupWindow.setHorizontalOffset(mHorizontalOffset);
            }

            if (mVerticalOffset != 0) {
                mPopupWindow.setVerticalOffset(mVerticalOffset);
            }

            if (mDropDownGravity != Gravity.NO_GRAVITY) {
                mPopupWindow.setDropDownGravity(mDropDownGravity);
            }

            if (mPromptView != null) {
                mPopupWindow.setPromptPosition(mPromptPosition);
                mPopupWindow.setPromptView(mPromptView);
            }
        }

        private void show() {
            configure();

            mInstrumentation.runOnMainSync(
                    () -> {
                        mPopupWindow.show();
                        assertTrue(mPopupWindow.isShowing());
                    });
            mInstrumentation.waitForIdleSync();
        }

        private void showAgain() {
            mInstrumentation.runOnMainSync(
                    () -> {
                        if (mPopupWindow == null || mPopupWindow.isShowing()) {
                            return;
                        }
                        mPopupWindow.show();
                        assertTrue(mPopupWindow.isShowing());
                    });
            mInstrumentation.waitForIdleSync();
        }

        private void dismiss() {
            mInstrumentation.runOnMainSync(
                    () -> {
                        if (mPopupWindow == null || !mPopupWindow.isShowing())
                            return;
                        mPopupWindow.dismiss();
                    });
            mInstrumentation.waitForIdleSync();
        }
    }
}
