/*
 * 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 android.support.v7.widget;

import android.support.annotation.Nullable;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
import android.view.View;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import static android.support.v7.widget.LinearLayoutManager.HORIZONTAL;
import static android.support.v7.widget.LinearLayoutManager.VERTICAL;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotSame;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.assertTrue;

@RunWith(Parameterized.class)
public class StaggeredGridLayoutManagerCacheTest extends BaseStaggeredGridLayoutManagerTest {

    final Config mConfig;
    final int mDx;
    final int mDy;

    public StaggeredGridLayoutManagerCacheTest(Config config, int dx, int dy) {
        mConfig = config;
        mDx = dx;
        mDy = dy;
    }

    @Parameterized.Parameters(name = "config:{0}, dx:{1}, dy: {2}")
    public static List<Object[]> getParams() {
        List<Object[]> result = new ArrayList<>();
        List<Config> configs = createBaseVariations();
        for (Config config : configs) {
            for (int dx : new int[] {-1, 0, 1}) {
                for (int dy : new int[] {-1, 0, 1}) {
                    result.add(new Object[]{config, dx, dy});
                }
            }
        }
        return result;
    }

    private ArrayList<RecyclerView.ViewHolder> cachedViews() {
        return mRecyclerView.mRecycler.mCachedViews;
    }

    private boolean cachedViewsContains(int position) {
        // Note: can't make assumptions about order here, so just check all cached views
        for (int i = 0; i < cachedViews().size(); i++) {
            if (cachedViews().get(i).getAdapterPosition() == position) return true;
        }
        return false;
    }

    public int findFirstVisibleItemPosition() {
        int[] positions = new int[mConfig.mSpanCount];
        mLayoutManager.findFirstVisibleItemPositions(positions);
        Arrays.sort(positions);
        return positions[0];
    }

    public int findLastVisibleItemPosition() {
        int[] positions = new int[mConfig.mSpanCount];
        mLayoutManager.findLastVisibleItemPositions(positions);
        Arrays.sort(positions);
        return positions[mConfig.mSpanCount - 1];
    }

    @MediumTest
    @Test
    public void cacheAndPrefetch() throws Throwable {
        final Config config = (Config) mConfig.clone();
        setupByConfig(config);
        waitFirstLayout();

        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                // pretend to have an extra 5s before next frame so prefetch won't abort early
                ((WrappedRecyclerView)mRecyclerView).setDrawingTimeOffset(5000);

                // scroll to the middle, so we can move in either direction
                mRecyclerView.scrollToPosition(mConfig.mItemCount / 2);
            }
        });

        mRecyclerView.setItemViewCacheSize(0);
        {
            mLayoutManager.expectPrefetch(1);
            runTestOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mRecyclerView.mRecycler.recycleAndClearCachedViews();
                    mRecyclerView.mViewPrefetcher.postFromTraversal(mDx, mDy);

                    // Lie about post time, so prefetch executes even if it is delayed
                    mRecyclerView.mViewPrefetcher.mPostTimeNanos += TimeUnit.SECONDS.toNanos(5);
                }
            });
            mLayoutManager.waitForPrefetch(1);
        }

        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                // validate cache state on UI thread
                if ((config.mOrientation == HORIZONTAL && mDx == 0)
                        || (config.mOrientation == VERTICAL && mDy == 0)) {
                    assertEquals(0, cachedViews().size());
                } else {
                    assertEquals(config.mSpanCount, cachedViews().size());

                    boolean reverseScroll = config.mOrientation == HORIZONTAL ? mDx < 0 : mDy < 0;
                    int lastVisibleItemPosition = findLastVisibleItemPosition();
                    int firstVisibleItemPosition = findFirstVisibleItemPosition();

                    for (int i = 0; i < config.mSpanCount; i++) {
                        if (mConfig.mReverseLayout == reverseScroll) {
                            // Pos scroll on pos layout, or reverse scroll on reverse layout
                            // = toward last
                            assertTrue(cachedViewsContains(lastVisibleItemPosition + 1 + i));
                        } else {
                            // Pos scroll on reverse layout, or reverse scroll on pos layout
                            // = toward first
                            assertTrue(cachedViewsContains(firstVisibleItemPosition - 1 - i));
                        }
                    }
                }
            }
        });
    }
}

@@ -669,35 +669,65 @@
 oid.
-sup
+os.Build;%0Aim
 port
-.annotation.Nullable
+ android.support.test.filters.SdkSuppress
 ;%0Aim
@@ -783,59 +783,8 @@
 est;
-%0Aimport android.util.Log;%0Aimport android.view.View;
 %0A%0Aim
@@ -935,38 +935,8 @@
 ys;%0A
-import java.util.Collections;%0A
 impo
@@ -995,58 +995,8 @@
 nit;
-%0Aimport java.util.concurrent.atomic.AtomicBoolean;
 %0A%0Aim
@@ -1233,144 +1233,102 @@
 sert
-NotSame;%0Aimport static junit.framework.Assert.assertSame;%0Aimport static junit.framework.Assert.assertTrue;%0A%0A@RunWith(Parameterized.class
+True;%0A%0A@RunWith(Parameterized.class)%0A@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP
 )%0Apu

Fix StaggaredGridLayoutManagerCacheTest to avoid older versions am: d8b7d71ac2 am: 0f2304fdd2 am: f41003acd0