/*
 * Copyright (C) 2008 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 static com.android.compatibility.common.util.CtsMockitoUtils.within;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.ActionMode;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.cts.util.TestUtils;
import android.widget.cts.util.TestUtilsMatchers;

import com.android.compatibility.common.util.CtsTouchUtils;
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.WidgetTestUtils;

import org.hamcrest.MatcherAssert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class AbsListViewTest {
    private static final String[] SHORT_LIST = new String[] { "This", "is", "short", "!" };

    private static final String[] COUNTRY_LIST = new String[] {
            "Argentina", "Armenia", "Aruba", "Australia", "Belarus", "Belgium", "Belize", "Benin",
            "Botswana", "Brazil", "Cameroon", "China", "Colombia", "Costa Rica", "Cyprus",
            "Denmark", "Djibouti", "Ethiopia", "Fiji", "Finland", "France", "Gabon", "Germany",
            "Ghana", "Haiti", "Honduras", "Iceland", "India", "Indonesia", "Ireland", "Italy",
            "Japan", "Kiribati", "Laos", "Lesotho", "Liberia", "Malaysia", "Mongolia", "Myanmar",
            "Nauru", "Norway", "Oman", "Pakistan", "Philippines", "Portugal", "Romania", "Russia",
            "Rwanda", "Singapore", "Slovakia", "Slovenia", "Somalia", "Swaziland", "Togo", "Tuvalu",
            "Uganda", "Ukraine", "United States", "Vanuatu", "Venezuela", "Zimbabwe"
    };

    @Rule
    public ActivityTestRule<ListViewCtsActivity> mActivityRule =
            new ActivityTestRule<>(ListViewCtsActivity.class);

    private Instrumentation mInstrumentation;
    private AbsListView mListView;
    private Context mContext;
    private AttributeSet mAttributeSet;
    private ArrayAdapter<String> mShortAdapter;
    private ArrayAdapter<String> mCountriesAdapter;
    private AbsListView.MultiChoiceModeListener mMultiChoiceModeListener;

    private static final float DELTA = 0.001f;

    @Before
    public void setup() throws Exception {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mContext = mInstrumentation.getTargetContext();

        final Activity activity = mActivityRule.getActivity();

        PollingCheck.waitFor(activity::hasWindowFocus);

        XmlPullParser parser = mContext.getResources().getXml(R.layout.listview_layout);
        WidgetTestUtils.beginDocument(parser, "FrameLayout");
        mAttributeSet = Xml.asAttributeSet(parser);

        mShortAdapter = new ArrayAdapter<>(mContext,
                android.R.layout.simple_list_item_1, SHORT_LIST);
        mCountriesAdapter = new ArrayAdapter<>(mContext,
                android.R.layout.simple_list_item_1, COUNTRY_LIST);

        mListView = (ListView) activity.findViewById(R.id.listview_default);
    }

    @Test
    @UiThreadTest
    public void testAccessFastScrollEnabled_UiThread() {
        mListView.setFastScrollAlwaysVisible(false);
        mListView.setFastScrollEnabled(false);
        assertFalse(mListView.isFastScrollEnabled());

        mListView.setFastScrollAlwaysVisible(true);
        mListView.setFastScrollEnabled(true);
        assertTrue(mListView.isFastScrollEnabled());
    }

    @Test
    public void testAccessFastScrollEnabled() {
        mListView.setFastScrollAlwaysVisible(false);
        mListView.setFastScrollEnabled(false);
        PollingCheck.waitFor(() -> !mListView.isFastScrollEnabled());

        mListView.setFastScrollAlwaysVisible(true);
        mListView.setFastScrollEnabled(true);
        PollingCheck.waitFor(mListView::isFastScrollEnabled);
    }

    @Test
    public void testAccessSmoothScrollbarEnabled() {
        mListView.setSmoothScrollbarEnabled(false);
        assertFalse(mListView.isSmoothScrollbarEnabled());

        mListView.setSmoothScrollbarEnabled(true);
        assertTrue(mListView.isSmoothScrollbarEnabled());
    }

    @Test
    public void testAccessScrollingCacheEnabled() {
        mListView.setScrollingCacheEnabled(false);
        assertFalse(mListView.isScrollingCacheEnabled());

        mListView.setScrollingCacheEnabled(true);
        assertTrue(mListView.isScrollingCacheEnabled());
    }

    private void setAdapter() throws Throwable {
        setAdapter(mCountriesAdapter);
    }

    private void setAdapter(final ListAdapter adapter) throws Throwable {
        mActivityRule.runOnUiThread(() -> mListView.setAdapter(adapter));
        mInstrumentation.waitForIdleSync();
    }

    private void setListSelection(int index) throws Throwable {
        mActivityRule.runOnUiThread(() -> mListView.setSelection(index));
        mInstrumentation.waitForIdleSync();
    }

    @LargeTest
    @Test
    public void testSetOnScrollListener() throws Throwable {
        AbsListView.OnScrollListener mockScrollListener =
                mock(AbsListView.OnScrollListener.class);

        verifyZeroInteractions(mockScrollListener);

        mListView.setOnScrollListener(mockScrollListener);
        verify(mockScrollListener, times(1)).onScroll(mListView, 0, 0, 0);
        verifyNoMoreInteractions(mockScrollListener);

        reset(mockScrollListener);

        setAdapter();
        verify(mockScrollListener, times(1)).onScroll(mListView, 0, mListView.getChildCount(),
                COUNTRY_LIST.length);
        verifyNoMoreInteractions(mockScrollListener);

        reset(mockScrollListener);

        CtsTouchUtils.emulateScrollToBottom(mInstrumentation, mListView);

        ArgumentCaptor<Integer> firstVisibleItemCaptor = ArgumentCaptor.forClass(Integer.class);
        ArgumentCaptor<Integer> visibleItemCountCaptor = ArgumentCaptor.forClass(Integer.class);
        verify(mockScrollListener, atLeastOnce()).onScroll(eq(mListView),
                firstVisibleItemCaptor.capture(), visibleItemCountCaptor.capture(),
                eq(COUNTRY_LIST.length));

        // We expect the first visible item values to be increasing
        MatcherAssert.assertThat(firstVisibleItemCaptor.getAllValues(),
                TestUtilsMatchers.inAscendingOrder());
        // The number of visible items during scrolling may change depending on the specific
        // scroll position. As such we only test this number at the very end
        final List<Integer> capturedVisibleItemCounts = visibleItemCountCaptor.getAllValues();
        assertEquals(mListView.getChildCount(),
                (int) capturedVisibleItemCounts.get(capturedVisibleItemCounts.size() - 1));

        ArgumentCaptor<Integer> scrollStateCaptor = ArgumentCaptor.forClass(Integer.class);
        verify(mockScrollListener, atLeastOnce()).onScrollStateChanged(eq(mListView),
                scrollStateCaptor.capture());

        // Verify that the last scroll state is IDLE
        final List<Integer> capturedScrollStates = scrollStateCaptor.getAllValues();
        assertEquals(AbsListView.OnScrollListener.SCROLL_STATE_IDLE,
                (int) capturedScrollStates.get(capturedScrollStates.size() - 1));
    }

    @LargeTest
    @Test
    public void testFling() throws Throwable {
        AbsListView.OnScrollListener mockScrollListener = mock(AbsListView.OnScrollListener.class);
        mListView.setOnScrollListener(mockScrollListener);

        setAdapter();

        // Fling down from top, expect a scroll.
        fling(10000, mockScrollListener);
        ArgumentCaptor<Integer> firstVisibleItemCaptor = ArgumentCaptor.forClass(Integer.class);
        verify(mockScrollListener, atLeastOnce()).onScroll(eq(mListView),
                firstVisibleItemCaptor.capture(), anyInt(), eq(COUNTRY_LIST.length));
        List<Integer> capturedFirstVisibleItems = firstVisibleItemCaptor.getAllValues();
        assertTrue(capturedFirstVisibleItems.get(capturedFirstVisibleItems.size() - 1) > 0);

        // Fling up the same amount, expect a scroll to the original position.
        fling(-10000, mockScrollListener);
        firstVisibleItemCaptor = ArgumentCaptor.forClass(Integer.class);
        verify(mockScrollListener, atLeastOnce()).onScroll(eq(mListView),
                firstVisibleItemCaptor.capture(), anyInt(), eq(COUNTRY_LIST.length));
        capturedFirstVisibleItems = firstVisibleItemCaptor.getAllValues();
        assertTrue(capturedFirstVisibleItems.get(capturedFirstVisibleItems.size() - 1) == 0);

        // Fling up again, expect no scroll, as the viewport is already at top.
        fling(-10000, mockScrollListener);
        verify(mockScrollListener, never()).onScroll(any(AbsListView.class), anyInt(), anyInt(),
                anyInt());

        // Fling up again with a huge velocity, expect no scroll.
        fling(-50000, mockScrollListener);
        verify(mockScrollListener, never()).onScroll(any(AbsListView.class), anyInt(), anyInt(),
                anyInt());
    }

    private void fling(int velocityY, OnScrollListener mockScrollListener) throws Throwable {
        reset(mockScrollListener);

        // Fling the list view
        mActivityRule.runOnUiThread(() -> mListView.fling(velocityY));

        // and wait until our mock listener is invoked with IDLE state
        verify(mockScrollListener, within(20000)).onScrollStateChanged(
                mListView, OnScrollListener.SCROLL_STATE_IDLE);
    }

    @Test
    public void testGetFocusedRect() throws Throwable {
        setAdapter(mShortAdapter);
        setListSelection(0);

        Rect r1 = new Rect();
        mListView.getFocusedRect(r1);

        assertEquals(0, r1.top);
        assertTrue(r1.bottom > 0);
        assertEquals(0, r1.left);
        assertTrue(r1.right > 0);

        setListSelection(3);
        Rect r2 = new Rect();
        mListView.getFocusedRect(r2);
        assertTrue(r2.top > 0);
        assertTrue(r2.bottom > 0);
        assertEquals(0, r2.left);
        assertTrue(r2.right > 0);

        assertTrue(r2.top > r1.top);
        assertEquals(r1.bottom - r1.top, r2.bottom - r2.top);
        assertEquals(r1.right, r2.right);
    }

    @Test
    public void testAccessStackFromBottom() throws Throwable {
        setAdapter();

        mActivityRule.runOnUiThread(() -> mListView.setStackFromBottom(false));
        assertFalse(mListView.isStackFromBottom());
        assertEquals(0, mListView.getSelectedItemPosition());

        mActivityRule.runOnUiThread(() -> mListView.setStackFromBottom(true));

        mInstrumentation.waitForIdleSync();
        assertTrue(mListView.isStackFromBottom());
        // ensure last item in list is selected
        assertEquals(COUNTRY_LIST.length-1, mListView.getSelectedItemPosition());
    }

    @Test
    public void testAccessSelectedItem() throws Throwable {
        assertNull(mListView.getSelectedView());

        setAdapter();

        final int lastVisiblePosition = mListView.getLastVisiblePosition();

        TextView tv = (TextView) mListView.getSelectedView();
        assertEquals(COUNTRY_LIST[0], tv.getText().toString());

        if (lastVisiblePosition >= 5) {
            setListSelection(5);
            tv = (TextView) mListView.getSelectedView();
            assertEquals(COUNTRY_LIST[5], tv.getText().toString());
        }

        if (lastVisiblePosition >= 2) {
            setListSelection(2);
            tv = (TextView) mListView.getSelectedView();
            assertEquals(COUNTRY_LIST[2], tv.getText().toString());
        }
    }

    @Test
    public void testAccessListPadding() throws Throwable {
        setAdapter();

        assertEquals(0, mListView.getListPaddingLeft());
        assertEquals(0, mListView.getListPaddingTop());
        assertEquals(0, mListView.getListPaddingRight());
        assertEquals(0, mListView.getListPaddingBottom());

        final Rect r = new Rect(0, 0, 40, 60);
        mActivityRule.runOnUiThread(
                () -> mListView.setPadding(r.left, r.top, r.right, r.bottom));
        mInstrumentation.waitForIdleSync();

        assertEquals(r.left, mListView.getListPaddingLeft());
        assertEquals(r.top, mListView.getListPaddingTop());
        assertEquals(r.right, mListView.getListPaddingRight());
        assertEquals(r.bottom, mListView.getListPaddingBottom());
    }

    @Test
    public void testAccessSelector() throws Throwable {
        setAdapter();

        final Drawable d = mContext.getDrawable(R.drawable.pass);
        mListView.setSelector(d);

        mActivityRule.runOnUiThread(mListView::requestLayout);
        mInstrumentation.waitForIdleSync();
        assertSame(d, mListView.getSelector());
        assertTrue(mListView.verifyDrawable(d));

        mListView.setSelector(R.drawable.failed);
        mListView.setDrawSelectorOnTop(true);

        mActivityRule.runOnUiThread(mListView::requestLayout);
        mInstrumentation.waitForIdleSync();

        Drawable drawable = mListView.getSelector();
        assertNotNull(drawable);
        final Rect r = drawable.getBounds();

        final TextView v = (TextView) mListView.getSelectedView();
        PollingCheck.waitFor(() -> v.getRight() == r.right);
        assertEquals(v.getLeft(), r.left);
        assertEquals(v.getTop(), r.top);
        assertEquals(v.getBottom(), r.bottom);
    }

    @Test
    public void testSetScrollIndicators() throws Throwable {
        final Activity activity = mActivityRule.getActivity();
        TextView tv1 = (TextView) activity.findViewById(R.id.headerview1);
        TextView tv2 = (TextView) activity.findViewById(R.id.footerview1);

        setAdapter();

        mListView.setScrollIndicators(tv1, tv2);

        mActivityRule.runOnUiThread(mListView::requestLayout);
        mInstrumentation.waitForIdleSync();
    }

    @Test
    public void testShowContextMenuForChild() throws Throwable {
        setAdapter();
        setListSelection(1);

        TextView tv = (TextView) mListView.getSelectedView();
        assertFalse(mListView.showContextMenuForChild(tv));

        // TODO: how to show the contextMenu success
    }

    @Test
    public void testPointToPosition() throws Throwable {
        assertEquals(AbsListView.INVALID_POSITION, mListView.pointToPosition(-1, -1));
        assertEquals(AbsListView.INVALID_ROW_ID, mListView.pointToRowId(-1, -1));

        setAdapter();

        View row = mListView.getChildAt(0);
        int rowHeight = row.getHeight();
        int middleOfSecondRow = rowHeight + rowHeight/2;

        int position1 = mListView.pointToPosition(0, 0);
        int position2 = mListView.pointToPosition(50, middleOfSecondRow);

        assertEquals(mCountriesAdapter.getItemId(position1), mListView.pointToRowId(0, 0));
        assertEquals(mCountriesAdapter.getItemId(position2),
                mListView.pointToRowId(50, middleOfSecondRow));

        assertTrue(position2 > position1);
    }

    @Test
    public void testSetRecyclerListener() throws Throwable {
        setAdapter();

        AbsListView.RecyclerListener mockRecyclerListener =
                mock(AbsListView.RecyclerListener.class);
        verifyZeroInteractions(mockRecyclerListener);

        mListView.setRecyclerListener(mockRecyclerListener);
        List<View> views = new ArrayList<>();
        mListView.reclaimViews(views);

        assertTrue(views.size() > 0);

        // Verify that onMovedToScrapHeap was called on each view in the order that they were
        // put in the list that we passed to reclaimViews
        final InOrder reclaimedOrder = inOrder(mockRecyclerListener);
        for (View reclaimed : views) {
            reclaimedOrder.verify(mockRecyclerListener, times(1)).onMovedToScrapHeap(reclaimed);
        }
        verifyNoMoreInteractions(mockRecyclerListener);
    }

    @Test
    public void testAccessCacheColorHint() {
        mListView.setCacheColorHint(Color.RED);
        assertEquals(Color.RED, mListView.getCacheColorHint());
        assertEquals(Color.RED, mListView.getSolidColor());

        mListView.setCacheColorHint(Color.LTGRAY);
        assertEquals(Color.LTGRAY, mListView.getCacheColorHint());
        assertEquals(Color.LTGRAY, mListView.getSolidColor());

        mListView.setCacheColorHint(Color.GRAY);
        assertEquals(Color.GRAY, mListView.getCacheColorHint());
        assertEquals(Color.GRAY, mListView.getSolidColor());
    }

    @Test
    public void testAccessTranscriptMode() {
        mListView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
        assertEquals(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL, mListView.getTranscriptMode());

        mListView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_DISABLED);
        assertEquals(AbsListView.TRANSCRIPT_MODE_DISABLED, mListView.getTranscriptMode());

        mListView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_NORMAL);
        assertEquals(AbsListView.TRANSCRIPT_MODE_NORMAL, mListView.getTranscriptMode());
    }

    @Test
    public void testCheckLayoutParams() {
        MyListView listView = new MyListView(mContext);

        AbsListView.LayoutParams param1 = new AbsListView.LayoutParams(10, 10);
        assertTrue(listView.checkLayoutParams(param1));

        ViewGroup.LayoutParams param2 = new ViewGroup.LayoutParams(10, 10);
        assertFalse(listView.checkLayoutParams(param2));
    }

    @Test
    public void testComputeVerticalScrollValues() {
        MyListView listView = new MyListView(mContext);
        assertEquals(0, listView.computeVerticalScrollRange());
        assertEquals(0, listView.computeVerticalScrollOffset());
        assertEquals(0, listView.computeVerticalScrollExtent());

        listView.setAdapter(mCountriesAdapter);
        listView.setSmoothScrollbarEnabled(false);
        assertEquals(mCountriesAdapter.getCount(), listView.computeVerticalScrollRange());
        assertEquals(0, listView.computeVerticalScrollOffset());
        assertEquals(0, listView.computeVerticalScrollExtent());

        listView.setSmoothScrollbarEnabled(true);
        assertEquals(0, listView.computeVerticalScrollOffset());
        assertEquals(0, listView.computeVerticalScrollExtent());
    }

    @Test
    public void testGenerateLayoutParams() throws XmlPullParserException, IOException {
        ViewGroup.LayoutParams res = mListView.generateLayoutParams(mAttributeSet);
        assertNotNull(res);
        assertTrue(res instanceof AbsListView.LayoutParams);

        MyListView listView = new MyListView(mContext);
        ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

        res = listView.generateLayoutParams(p);
        assertNotNull(res);
        assertTrue(res instanceof AbsListView.LayoutParams);
        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, res.width);
        assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, res.height);
    }

    @UiThreadTest
    @Test
    public void testBeforeAndAfterTextChanged() {
        // The java doc says these two methods do nothing
        CharSequence str = "test";
        SpannableStringBuilder sb = new SpannableStringBuilder();

        mListView.beforeTextChanged(str, 0, str.length(), str.length());
        mListView.afterTextChanged(sb);

        // test callback
        MyListView listView = new MyListView(mContext);
        TextView tv = new TextView(mContext);

        assertFalse(listView.isBeforeTextChangedCalled());
        assertFalse(listView.isOnTextChangedCalled());
        assertFalse(listView.isAfterTextChangedCalled());

        tv.addTextChangedListener(listView);
        assertFalse(listView.isBeforeTextChangedCalled());
        assertFalse(listView.isOnTextChangedCalled());
        assertFalse(listView.isAfterTextChangedCalled());

        tv.setText("abc");
        assertTrue(listView.isBeforeTextChangedCalled());
        assertTrue(listView.isOnTextChangedCalled());
        assertTrue(listView.isAfterTextChangedCalled());
    }

    @Test
    public void testAddTouchables() throws Throwable {
        ArrayList<View> views = new ArrayList<>();
        assertEquals(0, views.size());

        setAdapter();

        mListView.addTouchables(views);
        assertEquals(mListView.getChildCount(), views.size());
    }

    @Test
    public void testInvalidateViews() throws Throwable {
        final Activity activity = mActivityRule.getActivity();
        TextView tv1 = (TextView) activity.findViewById(R.id.headerview1);
        TextView tv2 = (TextView) activity.findViewById(R.id.footerview1);

        setAdapter();

        mListView.setScrollIndicators(tv1, tv2);

        mActivityRule.runOnUiThread(mListView::invalidateViews);
        mInstrumentation.waitForIdleSync();
    }

    @Test
    public void testGetContextMenuInfo() throws Throwable {
        final MyListView listView = new MyListView(mContext, mAttributeSet);

        mActivityRule.runOnUiThread(() ->  {
            mActivityRule.getActivity().setContentView(listView);
            listView.setAdapter(mCountriesAdapter);
            listView.setSelection(2);
        });
        mInstrumentation.waitForIdleSync();

        final TextView v = (TextView) listView.getSelectedView();
        assertNull(listView.getContextMenuInfo());

        final AbsListView.OnItemLongClickListener mockOnItemLongClickListener =
                mock(AbsListView.OnItemLongClickListener.class);
        listView.setOnItemLongClickListener(mockOnItemLongClickListener);

        verifyZeroInteractions(mockOnItemLongClickListener);

        // Now long click our view
        CtsTouchUtils.emulateLongPressOnViewCenter(mInstrumentation, v, 500);
        // and wait until our mock listener is invoked with the expected view
        verify(mockOnItemLongClickListener, within(5000)).onItemLongClick(listView, v, 2,
                listView.getItemIdAtPosition(2));

        ContextMenuInfo cmi = listView.getContextMenuInfo();
        assertNotNull(cmi);
    }

    @Test
    public void testGetTopBottomFadingEdgeStrength() {
        MyListView listView = new MyListView(mContext);

        assertEquals(0.0f, listView.getTopFadingEdgeStrength(), DELTA);
        assertEquals(0.0f, listView.getBottomFadingEdgeStrength(), DELTA);
    }

    @Test
    public void testHandleDataChanged() {
        MyListView listView = new MyListView(mContext, mAttributeSet, 0);
        listView.handleDataChanged();
        // TODO: how to check?
    }

    @UiThreadTest
    @Test
    public void testSetFilterText() {
        MyListView listView = new MyListView(mContext, mAttributeSet, 0);
        String filterText = "xyz";

        assertFalse(listView.isTextFilterEnabled());
        assertFalse(listView.hasTextFilter());
        assertFalse(listView.isInFilterMode());
        assertTrue(mListView.checkInputConnectionProxy(null));

        listView.setTextFilterEnabled(false);
        listView.setFilterText(filterText);
        assertFalse(listView.isTextFilterEnabled());
        assertFalse(listView.hasTextFilter());
        assertFalse(listView.isInFilterMode());

        listView.setTextFilterEnabled(true);
        listView.setFilterText(null);
        assertTrue(listView.isTextFilterEnabled());
        assertFalse(listView.hasTextFilter());
        assertFalse(listView.isInFilterMode());

        listView.setTextFilterEnabled(true);
        listView.setFilterText(filterText);
        assertTrue(listView.isTextFilterEnabled());
        assertTrue(listView.hasTextFilter());
        assertTrue(listView.isInFilterMode());

        listView.clearTextFilter();
        assertTrue(listView.isTextFilterEnabled());
        assertFalse(listView.hasTextFilter());
        assertFalse(listView.isInFilterMode());
    }

    @MediumTest
    @Test
    public void testSetItemChecked_multipleModeSameValue() throws Throwable {
        // Calling setItemChecked with the same value in multiple choice mode should not cause
        // requestLayout
        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(0, false));
        mInstrumentation.waitForIdleSync();
        assertFalse(mListView.isLayoutRequested());
        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(0, false));
        assertFalse(mListView.isLayoutRequested());
    }

    @MediumTest
    @Test
    public void testSetItemChecked_singleModeSameValue() throws Throwable {
        // Calling setItemChecked with the same value in single choice mode should not cause
        // requestLayout
        mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(0, false));
        mInstrumentation.waitForIdleSync();
        assertFalse(mListView.isLayoutRequested());
        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(0, false));
        assertFalse(mListView.isLayoutRequested());
    }

    @MediumTest
    @Test
    public void testSetItemChecked_multipleModeDifferentValue() throws Throwable {
        // Calling setItemChecked with a different value in multiple choice mode should cause
        // requestLayout
        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(0, false));
        mInstrumentation.waitForIdleSync();
        assertFalse(mListView.isLayoutRequested());
        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(0, true));
        assertTrue(mListView.isLayoutRequested());
    }

    @MediumTest
    @Test
    public void testSetItemChecked_singleModeDifferentValue() throws Throwable {
        // Calling setItemChecked with a different value in single choice mode should cause
        // requestLayout
        mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(0, false));
        mInstrumentation.waitForIdleSync();
        assertFalse(mListView.isLayoutRequested());
        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(0, true));
        assertTrue(mListView.isLayoutRequested());
    }

    @LargeTest
    @Test
    public void testTextFilter() throws Throwable {
        setAdapter();

        // Default state - no text filter
        assertFalse(mListView.isTextFilterEnabled());
        assertFalse(mListView.hasTextFilter());
        assertTrue(TextUtils.isEmpty(mListView.getTextFilter()));

        // Enable text filter and verify that while it's enabled, the filtering is
        // still no on
        mActivityRule.runOnUiThread(() -> mListView.setTextFilterEnabled(true));
        assertTrue(mListView.isTextFilterEnabled());
        assertFalse(mListView.hasTextFilter());
        assertTrue(TextUtils.isEmpty(mListView.getTextFilter()));

        // Verify the initial content of the list
        assertEquals(COUNTRY_LIST.length, mListView.getCount());

        // Set text filter to A - we expect four entries to be left displayed in the list
        mActivityRule.runOnUiThread(() -> mListView.setFilterText("A"));
        PollingCheck.waitFor(() -> mListView.getCount() == 4);
        assertTrue(mListView.isTextFilterEnabled());
        assertTrue(mListView.hasTextFilter());
        assertTrue(TextUtils.equals("A", mListView.getTextFilter()));

        // Set text filter to Ar - we expect three entries to be left displayed in the list
        mActivityRule.runOnUiThread(() -> mListView.setFilterText("Ar"));
        PollingCheck.waitFor(() -> mListView.getCount() == 3);
        assertTrue(mListView.isTextFilterEnabled());
        assertTrue(mListView.hasTextFilter());
        assertTrue(TextUtils.equals("Ar", mListView.getTextFilter()));

        // Clear text filter - we expect to go back to the initial content
        mActivityRule.runOnUiThread(() -> mListView.clearTextFilter());
        PollingCheck.waitFor(() -> mListView.getCount() == COUNTRY_LIST.length);
        assertTrue(mListView.isTextFilterEnabled());
        assertFalse(mListView.hasTextFilter());
        assertTrue(TextUtils.isEmpty(mListView.getTextFilter()));

        // Set text filter to Be - we expect four entries to be left displayed in the list
        mActivityRule.runOnUiThread(() -> mListView.setFilterText("Be"));
        PollingCheck.waitFor(() -> mListView.getCount() == 4);
        assertTrue(mListView.isTextFilterEnabled());
        assertTrue(mListView.hasTextFilter());
        assertTrue(TextUtils.equals("Be", mListView.getTextFilter()));

        // Set text filter to Q - we no entries displayed in the list
        mActivityRule.runOnUiThread(() -> mListView.setFilterText("Q"));
        PollingCheck.waitFor(() -> mListView.getCount() == 0);
        assertTrue(mListView.isTextFilterEnabled());
        assertTrue(mListView.hasTextFilter());
        assertTrue(TextUtils.equals("Q", mListView.getTextFilter()));
    }

    @Test
    public void testOnFilterComplete() throws Throwable {
        // Note that we're not using spy() due to Mockito not being able to spy on ListView,
        // at least yet.
        final MyListView listView = new MyListView(mContext, mAttributeSet);

        mActivityRule.runOnUiThread(() -> {
            mActivityRule.getActivity().setContentView(listView);
            listView.setAdapter(mCountriesAdapter);
            listView.setTextFilterEnabled(true);
        });
        mInstrumentation.waitForIdleSync();

        // Set text filter to A - we expect four entries to be left displayed in the list
        mActivityRule.runOnUiThread(() -> listView.setFilterText("A"));
        PollingCheck.waitFor(() -> listView.getCount() == 4);
        assertTrue(listView.isTextFilterEnabled());
        assertTrue(listView.hasTextFilter());
        assertTrue(TextUtils.equals("A", listView.getTextFilter()));

        assertEquals(4, listView.getOnFilterCompleteCount());
    }

    private static class PositionArrayAdapter<T> extends ArrayAdapter<T> {
        public PositionArrayAdapter(Context context, int resource, List<T> objects) {
            super(context, resource, objects);
        }

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

        @Override
        public boolean hasStableIds() {
            return true;
        }
    }

    private void verifyCheckedState(final long[] expectedCheckedItems) {
        TestUtils.assertIdentical(expectedCheckedItems, mListView.getCheckedItemIds());

        assertEquals(expectedCheckedItems.length, mListView.getCheckedItemCount());

        final long expectedCheckedItemPosition =
                (mListView.getChoiceMode() == AbsListView.CHOICE_MODE_SINGLE) &&
                        (expectedCheckedItems.length == 1)
                        ? expectedCheckedItems[0]
                        : AbsListView.INVALID_POSITION;
        assertEquals(expectedCheckedItemPosition, mListView.getCheckedItemPosition());

        // Note that getCheckedItemPositions doesn't have a guarantee that it only holds
        // true values, which is why we're not doing the size() == 0 check even in the initial
        // state
        TestUtils.assertTrueValuesAtPositions(
                expectedCheckedItems, mListView.getCheckedItemPositions());
    }

    @MediumTest
    @Test
    public void testCheckedItemsUnderNoneChoiceMode() throws Throwable {
        final ArrayList<String> items = new ArrayList<>(Arrays.asList(COUNTRY_LIST));
        final ArrayAdapter<String> adapter = new PositionArrayAdapter<>(mContext,
                android.R.layout.simple_list_item_1, items);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mListView,
                () -> mListView.setAdapter(adapter));

        mActivityRule.runOnUiThread(
                () -> mListView.setChoiceMode(AbsListView.CHOICE_MODE_NONE));
        verifyCheckedState(new long[] {});

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(2, true));
        verifyCheckedState(new long[] {});

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(4, true));
        verifyCheckedState(new long[] {});

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(2, false));
        verifyCheckedState(new long[] {});

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(4, false));
        verifyCheckedState(new long[] {});
    }

    @MediumTest
    @Test
    public void testCheckedItemsUnderSingleChoiceMode() throws Throwable {
        final ArrayList<String> items = new ArrayList<>(Arrays.asList(COUNTRY_LIST));
        final ArrayAdapter<String> adapter = new PositionArrayAdapter<>(mContext,
                android.R.layout.simple_list_item_1, items);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mListView,
                () -> mListView.setAdapter(adapter));

        mActivityRule.runOnUiThread(
                () -> mListView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE));
        verifyCheckedState(new long[] {});

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(2, true));
        verifyCheckedState(new long[] { 2 });

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(4, true));
        verifyCheckedState(new long[] { 4 });

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(2, false));
        verifyCheckedState(new long[] { 4 });

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(4, false));
        verifyCheckedState(new long[] {});
    }

    @MediumTest
    @Test
    public void testCheckedItemsUnderMultipleChoiceMode() throws Throwable {
        final ArrayList<String> items = new ArrayList<>(Arrays.asList(COUNTRY_LIST));
        final ArrayAdapter<String> adapter = new PositionArrayAdapter<>(mContext,
                android.R.layout.simple_list_item_1, items);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mListView,
                () -> mListView.setAdapter(adapter));

        mActivityRule.runOnUiThread(
                () -> mListView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE));
        verifyCheckedState(new long[] {});

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(2, true));
        verifyCheckedState(new long[] { 2 });

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(4, true));
        verifyCheckedState(new long[] { 2, 4 });

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(2, false));
        verifyCheckedState(new long[] { 4 });

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(4, false));
        verifyCheckedState(new long[] {});
    }

    private void configureMultiChoiceModalState() throws Throwable {
        final ArrayList<String> items = new ArrayList<>(Arrays.asList(COUNTRY_LIST));
        final ArrayAdapter<String> adapter = new PositionArrayAdapter<>(mContext,
                android.R.layout.simple_list_item_1, items);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mListView,
                () -> mListView.setAdapter(adapter));

        // Configure a multi-choice mode listener to configure our test contextual action bar
        // content. We will subsequently query that listener for calls to its
        // onItemCheckedStateChanged method
        mMultiChoiceModeListener =
                mock(AbsListView.MultiChoiceModeListener.class);
        doAnswer((InvocationOnMock invocation) -> {
            final ActionMode actionMode = (ActionMode) invocation.getArguments() [0];
            final Menu menu = (Menu) invocation.getArguments() [1];
            actionMode.getMenuInflater().inflate(R.menu.cab_menu, menu);
            return true;
        }).when(mMultiChoiceModeListener).onCreateActionMode(
                any(ActionMode.class), any(Menu.class));
        mListView.setMultiChoiceModeListener(mMultiChoiceModeListener);

        mActivityRule.runOnUiThread(
                () -> mListView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL));
        verifyCheckedState(new long[] {});
    }

    @MediumTest
    @Test
    public void testCheckedItemsUnderMultipleModalChoiceMode() throws Throwable {
        configureMultiChoiceModalState();

        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(2, true));
        verifyCheckedState(new long[] { 2 });
        verify(mMultiChoiceModeListener, times(1)).onItemCheckedStateChanged(
                any(ActionMode.class), eq(2), eq(2L), eq(true));

        reset(mMultiChoiceModeListener);
        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(4, true));
        verifyCheckedState(new long[] { 2, 4 });
        verify(mMultiChoiceModeListener, times(1)).onItemCheckedStateChanged(
                any(ActionMode.class), eq(4), eq(4L), eq(true));

        reset(mMultiChoiceModeListener);
        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(2, false));
        verifyCheckedState(new long[] { 4 });
        verify(mMultiChoiceModeListener, times(1)).onItemCheckedStateChanged(
                any(ActionMode.class), eq(2), eq(2L), eq(false));

        reset(mMultiChoiceModeListener);
        mActivityRule.runOnUiThread(() -> mListView.setItemChecked(4, false));
        verifyCheckedState(new long[] {});
        mListView.setMultiChoiceModeListener(mMultiChoiceModeListener);
        verify(mMultiChoiceModeListener, times(1)).onItemCheckedStateChanged(
                any(ActionMode.class), eq(4), eq(4L), eq(false));
    }

    @LargeTest
    @Test
    public void testMultiSelectionWithLongPressAndTaps() throws Throwable {
        configureMultiChoiceModalState();

        final int firstVisiblePosition = mListView.getFirstVisiblePosition();
        final int lastVisiblePosition = mListView.getLastVisiblePosition();

        // Emulate long-click on the middle item of the currently visible content
        final int positionForInitialSelection = (firstVisiblePosition + lastVisiblePosition) / 2;
        CtsTouchUtils.emulateLongPressOnViewCenter(mInstrumentation,
                mListView.getChildAt(positionForInitialSelection));
        // wait until our listener has been notified that the item has been checked
        verify(mMultiChoiceModeListener, within(1000)).onItemCheckedStateChanged(
                any(ActionMode.class), eq(positionForInitialSelection),
                eq((long) positionForInitialSelection), eq(true));
        // and verify the overall checked state of our list
        verifyCheckedState(new long[] { positionForInitialSelection });

        if (firstVisiblePosition != positionForInitialSelection) {
            // Tap the first element in our list
            CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation,
                    mListView.getChildAt(firstVisiblePosition));
            // wait until our listener has been notified that the item has been checked
            verify(mMultiChoiceModeListener, within(1000)).onItemCheckedStateChanged(
                    any(ActionMode.class), eq(firstVisiblePosition),
                    eq((long) firstVisiblePosition), eq(true));
            // and verify the overall checked state of our list
            verifyCheckedState(new long[] { firstVisiblePosition, positionForInitialSelection });
        }

        // Scroll down
        CtsTouchUtils.emulateScrollToBottom(mInstrumentation, mListView);
        final int lastListPosition = COUNTRY_LIST.length - 1;
        if (lastListPosition != positionForInitialSelection) {
            // Tap the last element in our list
            CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation,
                    mListView.getChildAt(mListView.getChildCount() - 1));
            // wait until our listener has been notified that the item has been checked
            verify(mMultiChoiceModeListener, within(1000)).onItemCheckedStateChanged(
                    any(ActionMode.class), eq(lastListPosition),
                    eq((long) lastListPosition), eq(true));
            // and verify the overall checked state of our list
            verifyCheckedState(new long[] { firstVisiblePosition, positionForInitialSelection,
                    lastListPosition });
        }
    }

    // Helper method that emulates fast scroll by dragging along the right edge of our ListView.
    private void verifyFastScroll() throws Throwable {
        setAdapter();

        final int lastVisiblePosition = mListView.getLastVisiblePosition();
        if (lastVisiblePosition == (COUNTRY_LIST.length - 1)) {
            // This can happen on very large screens - the entire content fits and there's
            // nothing to scroll
            return;
        }

        mActivityRule.runOnUiThread(() -> mListView.setFastScrollAlwaysVisible(true));
        mInstrumentation.waitForIdleSync();
        assertTrue(mListView.isFastScrollEnabled());
        assertTrue(mListView.isFastScrollAlwaysVisible());

        final int[] listViewOnScreenXY = new int[2];
        mListView.getLocationOnScreen(listViewOnScreenXY);

        final int topEdgeY = listViewOnScreenXY[1];
        final int bottomEdgeY = listViewOnScreenXY[1] + mListView.getHeight();
        final int rightEdgeX = listViewOnScreenXY[0] + mListView.getWidth();

        // Emulate a downwards gesture that should bring us all the way to the last element
        // of the list (when fast scroll is enabled)
        CtsTouchUtils.emulateDragGesture(mInstrumentation,
                rightEdgeX - 1,              // X start of the drag
                topEdgeY + 1,                // Y start of the drag
                0,                           // X amount of the drag (vertical)
                mListView.getHeight() - 2);  // Y amount of the drag (downwards)

        assertEquals(COUNTRY_LIST.length - 1, mListView.getLastVisiblePosition());

        // Emulate an upwards gesture that should bring us all the way to the first element
        // of the list (when fast scroll is enabled)
        CtsTouchUtils.emulateDragGesture(mInstrumentation,
                rightEdgeX - 1,               // X start of the drag
                bottomEdgeY - 1,              // Y start of the drag
                0,                            // X amount of the drag (vertical)
                -mListView.getHeight() + 2);  // Y amount of the drag (upwards)

        assertEquals(0, mListView.getFirstVisiblePosition());
    }

    @LargeTest
    @Test
    public void testFastScroll() throws Throwable {
        verifyFastScroll();
    }

    @LargeTest
    @Test
    public void testFastScrollStyle() throws Throwable {
        mListView.setFastScrollStyle(R.style.FastScrollCustomStyle);

        verifyFastScroll();
    }

    /**
     * MyListView for test.
     */
    private static class MyListView extends ListView {
        public MyListView(Context context) {
            super(context);
        }

        public MyListView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public MyListView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

        @Override
        protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
            return super.checkLayoutParams(p);
        }

        @Override
        protected int computeVerticalScrollExtent() {
            return super.computeVerticalScrollExtent();
        }

        @Override
        protected int computeVerticalScrollOffset() {
            return super.computeVerticalScrollOffset();
        }

        @Override
        protected int computeVerticalScrollRange() {
            return super.computeVerticalScrollRange();
        }

        @Override
        protected void dispatchDraw(Canvas canvas) {
            super.dispatchDraw(canvas);
        }

        @Override
        protected void dispatchSetPressed(boolean pressed) {
            super.dispatchSetPressed(pressed);
        }

        @Override
        protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
            return super.generateLayoutParams(p);
        }

        @Override
        protected float getBottomFadingEdgeStrength() {
            return super.getBottomFadingEdgeStrength();
        }

        @Override
        protected ContextMenuInfo getContextMenuInfo() {
            return super.getContextMenuInfo();
        }

        @Override
        protected float getTopFadingEdgeStrength() {
            return super.getTopFadingEdgeStrength();
        }

        @Override
        protected void handleDataChanged() {
            super.handleDataChanged();
        }

        @Override
        protected boolean isInFilterMode() {
            return super.isInFilterMode();
        }

        private boolean mIsBeforeTextChangedCalled;
        private boolean mIsOnTextChangedCalled;
        private boolean mIsAfterTextChangedCalled;

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            mIsBeforeTextChangedCalled = true;
            super.beforeTextChanged(s, start, count, after);
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            mIsOnTextChangedCalled = true;
            super.onTextChanged(s, start, before, count);
        }

        @Override
        public void afterTextChanged(Editable s) {
            mIsAfterTextChangedCalled = true;
            super.afterTextChanged(s);
        }

        public boolean isBeforeTextChangedCalled() {
            return mIsBeforeTextChangedCalled;
        }

        public boolean isOnTextChangedCalled() {
            return mIsOnTextChangedCalled;
        }

        public boolean isAfterTextChangedCalled() {
            return mIsAfterTextChangedCalled;
        }

        private int mOnFilterCompleteCount = -1;

        @Override
        public void onFilterComplete(int count) {
            super.onFilterComplete(count);
            mOnFilterCompleteCount = count;
        }

        public int getOnFilterCompleteCount() {
            return mOnFilterCompleteCount;
        }
    }
}
