/*
 * Copyright (C) 2017 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.
 */

@file:OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
@file:Suppress("DEPRECATION")

package androidx.paging

import androidx.paging.ItemKeyedDataSourceTest.ItemDataSource
import androidx.paging.PagedList.BoundaryCallback
import androidx.paging.PagedList.Callback
import androidx.paging.PagedList.Config
import androidx.paging.PagingSource.LoadResult.Page
import androidx.testutils.TestDispatcher
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.reset
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
import com.nhaarman.mockitokotlin2.verifyZeroInteractions
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertSame
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import kotlin.test.assertFailsWith
import kotlin.test.assertNotSame

@RunWith(Parameterized::class)
class ContiguousPagedListTest(private val placeholdersEnabled: Boolean) {
    private val mainThread = TestDispatcher()
    private val backgroundThread = TestDispatcher()

    private class Item(position: Int) {
        val pos: Int = position
        val name: String = "Item $position"

        override fun toString(): String = name
    }

    /**
     * Note: we use a non-positional dataSource here because we want to avoid the initial load size
     * and alignment restrictions. These tests were written before positional+contiguous enforced
     * these behaviors.
     */
    private inner class TestPagingSource(val listData: List<Item> = ITEMS) :
        PagingSource<Int, Item>() {
        override fun getRefreshKey(state: PagingState<Int, Item>): Int? {
            return state.anchorPosition
                ?.let { anchorPosition -> state.closestItemToPosition(anchorPosition)?.pos }
                ?: 0
        }

        override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Item> {
            return when (params.loadType) {
                LoadType.REFRESH -> loadInitial(params)
                LoadType.START -> loadBefore(params)
                LoadType.END -> loadAfter(params)
            }
        }

        fun enqueueErrorForIndex(index: Int) {
            errorIndices.add(index)
        }

        val errorIndices = mutableListOf<Int>()

        private fun loadInitial(params: LoadParams<Int>): LoadResult<Int, Item> {
            val initPos = params.key ?: 0
            val start = maxOf(initPos - params.loadSize / 2, 0)

            val result = getClampedRange(start, start + params.loadSize)
            return when {
                result == null -> LoadResult.Error(EXCEPTION)
                placeholdersEnabled -> Page(
                    data = result,
                    prevKey = result.firstOrNull()?.pos,
                    nextKey = result.lastOrNull()?.pos,
                    itemsBefore = start,
                    itemsAfter = listData.size - result.size - start
                )
                else -> Page(
                    data = result,
                    prevKey = result.firstOrNull()?.pos,
                    nextKey = result.lastOrNull()?.pos
                )
            }
        }

        private fun loadAfter(params: LoadParams<Int>): LoadResult<Int, Item> {
            val result = getClampedRange(params.key!! + 1, params.key!! + 1 + params.loadSize)
                ?: return LoadResult.Error(EXCEPTION)
            return Page(
                data = result,
                prevKey = if (result.isNotEmpty()) result.first().pos else null,
                nextKey = if (result.isNotEmpty()) result.last().pos else null
            )
        }

        private fun loadBefore(params: LoadParams<Int>): LoadResult<Int, Item> {
            val result = getClampedRange(params.key!! - params.loadSize, params.key!!)
                ?: return LoadResult.Error(EXCEPTION)
            return Page(
                data = result,
                prevKey = result.firstOrNull()?.pos,
                nextKey = result.lastOrNull()?.pos
            )
        }

        private fun getClampedRange(startInc: Int, endExc: Int): List<Item>? {
            val matching = errorIndices.filter { it in startInc until endExc }
            if (matching.isNotEmpty()) {
                // found indices with errors enqueued - fail to load them
                errorIndices.removeAll(matching)
                return null
            }
            return listData.subList(maxOf(0, startInc), minOf(listData.size, endExc))
        }
    }

    private fun PagingSource<*, Item>.enqueueErrorForIndex(index: Int) {
        (this as TestPagingSource).enqueueErrorForIndex(index)
    }

    private fun <E> MutableList<E>.getAllAndClear(): List<E> {
        val data = this.toList()
        assertNotSame(data, this)
        this.clear()
        return data
    }

    private fun <E : Any> PagedList<E>.addLoadStateCapture(desiredType: LoadType):
            Pair<Any, MutableList<StateChange>> {
        val list = mutableListOf<StateChange>()
        val listener = { type: LoadType, state: LoadState ->
            if (type == desiredType) {
                list.add(StateChange(type, state))
            }
        }
        addWeakLoadStateListener(listener)
        return Pair(listener, list)
    }

    private fun verifyRange(start: Int, count: Int, actual: PagedStorage<Item>) {
        if (placeholdersEnabled) {
            // assert nulls + content
            val expected = arrayOfNulls<Item>(ITEMS.size)
            System.arraycopy(ITEMS.toTypedArray(), start, expected, start, count)
            assertEquals(expected.toList(), actual)

            val expectedTrailing = ITEMS.size - start - count
            assertEquals(ITEMS.size, actual.size)
            assertEquals(start, actual.placeholdersStart)
            assertEquals(expectedTrailing, actual.placeholdersEnd)
        } else {
            assertEquals(ITEMS.subList(start, start + count), actual)

            assertEquals(count, actual.size)
            assertEquals(0, actual.placeholdersStart)
            assertEquals(0, actual.placeholdersEnd)
        }
        assertEquals(count, actual.storageCount)
    }

    private fun verifyRange(start: Int, count: Int, actual: PagedList<Item>) {
        verifyRange(start, count, actual.storage)
        assertEquals(count, actual.loadedCount)
    }

    private fun PagingSource<Int, Item>.getInitialPage(
        initialKey: Int,
        loadSize: Int,
        pageSize:
        Int
    ): Page<Int, Item> = runBlocking {
        val result = load(
            PagingSource.LoadParams(
                LoadType.REFRESH,
                initialKey,
                loadSize,
                placeholdersEnabled,
                pageSize
            )
        )

        result as? Page ?: throw RuntimeException("Unexpected load failure")
    }

    private fun createCountedPagedList(
        initialPosition: Int?,
        pageSize: Int = 20,
        initLoadSize: Int = 40,
        prefetchDistance: Int = 20,
        listData: List<Item> = ITEMS,
        boundaryCallback: BoundaryCallback<Item>? = null,
        maxSize: Int = Config.MAX_SIZE_UNBOUNDED,
        pagingSource: PagingSource<Int, Item> = TestPagingSource(listData)
    ): PagedList<Item> {
        val initialPage = pagingSource.getInitialPage(
            initialPosition ?: 0,
            initLoadSize,
            pageSize
        )

        val config = Config.Builder()
            .setPageSize(pageSize)
            .setInitialLoadSizeHint(initLoadSize)
            .setPrefetchDistance(prefetchDistance)
            .setMaxSize(maxSize)
            .setEnablePlaceholders(placeholdersEnabled)
            .build()

        return PagedList.Builder(pagingSource, initialPage, config)
            .setBoundaryCallback(boundaryCallback)
            .setFetchDispatcher(backgroundThread)
            .setNotifyDispatcher(mainThread)
            .setInitialKey(initialPosition)
            .build()
    }

    @Test
    fun construct() {
        val pagedList = createCountedPagedList(0)
        verifyRange(0, 40, pagedList)
    }

    @Test
    fun getDataSource() {
        // Create a pagedList with a pagingSource directly.
        val pagedListWithPagingSource = createCountedPagedList(0)
        @Suppress("DEPRECATION")
        assertFailsWith<IllegalStateException> { pagedListWithPagingSource.dataSource }

        @Suppress("DEPRECATION")
        val pagedListWithDataSource = PagedList.Builder(ItemDataSource(), 10).build()

        @Suppress("DEPRECATION")
        assertTrue(pagedListWithDataSource.dataSource is ItemDataSource)

        // snapshot keeps same DataSource
        @Suppress("DEPRECATION")
        assertSame(
            pagedListWithDataSource.dataSource,
            (pagedListWithDataSource.snapshot() as SnapshotPagedList<*>).dataSource
        )
    }

    @Test
    fun getPagingSource() {
        val pagedList = createCountedPagedList(0)
        assertTrue(pagedList.pagingSource is TestPagingSource)

        // snapshot keeps same DataSource
        @Suppress("DEPRECATION")
        assertSame(
            pagedList.pagingSource,
            (pagedList.snapshot() as SnapshotPagedList<Item>).pagingSource
        )
    }

    @Test(expected = IndexOutOfBoundsException::class)
    fun loadAroundNegative() {
        val pagedList = createCountedPagedList(0)
        pagedList.loadAround(-1)
    }

    @Test(expected = IndexOutOfBoundsException::class)
    fun loadAroundTooLarge() {
        val pagedList = createCountedPagedList(0)
        pagedList.loadAround(pagedList.size)
    }

    private fun verifyCallback(
        callback: Callback,
        countedPosition: Int,
        uncountedPosition: Int
    ) {
        if (placeholdersEnabled) {
            verify(callback).onChanged(countedPosition, 20)
        } else {
            verify(callback).onInserted(uncountedPosition, 20)
        }
    }

    private fun verifyCallback(callback: Callback, position: Int) {
        verifyCallback(callback, position, position)
    }

    private fun verifyDropCallback(
        callback: Callback,
        countedPosition: Int,
        uncountedPosition: Int
    ) {
        if (placeholdersEnabled) {
            verify(callback).onChanged(countedPosition, 20)
        } else {
            verify(callback).onRemoved(uncountedPosition, 20)
        }
    }

    private fun verifyDropCallback(callback: Callback, position: Int) {
        verifyDropCallback(callback, position, position)
    }

    @Test
    fun append() {
        val pagedList = createCountedPagedList(0)
        val callback = mock<Callback>()
        pagedList.addWeakCallback(callback)
        verifyRange(0, 40, pagedList)
        verifyZeroInteractions(callback)

        pagedList.loadAround(35)
        drain()

        verifyRange(0, 60, pagedList)
        verifyCallback(callback, 40)
        verifyNoMoreInteractions(callback)
    }

    @Test
    fun prepend() {
        val pagedList = createCountedPagedList(80)
        val callback = mock<Callback>()
        pagedList.addWeakCallback(callback)
        verifyRange(60, 40, pagedList)
        verifyZeroInteractions(callback)

        pagedList.loadAround(if (placeholdersEnabled) 65 else 5)
        drain()

        verifyRange(40, 60, pagedList)
        verifyCallback(callback, 40, 0)
        verifyNoMoreInteractions(callback)
    }

    @Test
    fun outwards() {
        val pagedList = createCountedPagedList(40)
        val callback = mock<Callback>()
        pagedList.addWeakCallback(callback)
        verifyRange(20, 40, pagedList)
        verifyZeroInteractions(callback)

        pagedList.loadAround(if (placeholdersEnabled) 55 else 35)
        drain()

        verifyRange(20, 60, pagedList)
        verifyCallback(callback, 60, 40)
        verifyNoMoreInteractions(callback)

        pagedList.loadAround(if (placeholdersEnabled) 25 else 5)
        drain()

        verifyRange(0, 80, pagedList)
        verifyCallback(callback, 0, 0)
        verifyNoMoreInteractions(callback)
    }

    @Test
    fun prefetchRequestedPrepend() {
        assertEquals(10, ContiguousPagedList.getPrependItemsRequested(10, 0, 0))
        assertEquals(15, ContiguousPagedList.getPrependItemsRequested(10, 0, 5))
        assertEquals(0, ContiguousPagedList.getPrependItemsRequested(1, 41, 40))
        assertEquals(1, ContiguousPagedList.getPrependItemsRequested(1, 40, 40))
    }

    @Test
    fun prefetchRequestedAppend() {
        assertEquals(10, ContiguousPagedList.getAppendItemsRequested(10, 9, 10))
        assertEquals(15, ContiguousPagedList.getAppendItemsRequested(10, 9, 5))
        assertEquals(0, ContiguousPagedList.getAppendItemsRequested(1, 8, 10))
        assertEquals(1, ContiguousPagedList.getAppendItemsRequested(1, 9, 10))
    }

    @Test
    fun prefetchFront() {
        val pagedList = createCountedPagedList(
            initialPosition = 50,
            pageSize = 20,
            initLoadSize = 20,
            prefetchDistance = 1
        )
        verifyRange(40, 20, pagedList)

        // access adjacent to front, shouldn't trigger prefetch
        pagedList.loadAround(if (placeholdersEnabled) 41 else 1)
        drain()
        verifyRange(40, 20, pagedList)

        // access front item, should trigger prefetch
        pagedList.loadAround(if (placeholdersEnabled) 40 else 0)
        drain()
        verifyRange(20, 40, pagedList)
    }

    @Test
    fun prefetchEnd() {
        val pagedList = createCountedPagedList(
            initialPosition = 50,
            pageSize = 20,
            initLoadSize = 20,
            prefetchDistance = 1
        )
        verifyRange(40, 20, pagedList)

        // access adjacent from end, shouldn't trigger prefetch
        pagedList.loadAround(if (placeholdersEnabled) 58 else 18)
        drain()
        verifyRange(40, 20, pagedList)

        // access end item, should trigger prefetch
        pagedList.loadAround(if (placeholdersEnabled) 59 else 19)
        drain()
        verifyRange(40, 40, pagedList)
    }

    @Test
    fun pageDropEnd() {
        val pagedList = createCountedPagedList(
            initialPosition = 0,
            pageSize = 20,
            initLoadSize = 20,
            prefetchDistance = 1,
            maxSize = 70
        )
        val callback = mock<Callback>()
        pagedList.addWeakCallback(callback)
        verifyRange(0, 20, pagedList)
        verifyZeroInteractions(callback)

        // load 2nd page
        pagedList.loadAround(19)
        drain()
        verifyRange(0, 40, pagedList)
        verifyCallback(callback, 20)
        verifyNoMoreInteractions(callback)

        // load 3rd page
        pagedList.loadAround(39)
        drain()
        verifyRange(0, 60, pagedList)
        verifyCallback(callback, 40)
        verifyNoMoreInteractions(callback)

        // load 4th page, drop 1st
        pagedList.loadAround(59)
        drain()
        verifyRange(20, 60, pagedList)
        verifyCallback(callback, 60)
        verifyDropCallback(callback, 0)
        verifyNoMoreInteractions(callback)
    }

    @Test
    fun pageDropFront() {
        val pagedList = createCountedPagedList(
            initialPosition = 90,
            pageSize = 20,
            initLoadSize = 20,
            prefetchDistance = 1,
            maxSize = 70
        )
        val callback = mock<Callback>()
        pagedList.addWeakCallback(callback)
        verifyRange(80, 20, pagedList)
        verifyZeroInteractions(callback)

        // load 4th page
        pagedList.loadAround(if (placeholdersEnabled) 80 else 0)
        drain()
        verifyRange(60, 40, pagedList)
        verifyCallback(callback, 60, 0)
        verifyNoMoreInteractions(callback)
        reset(callback)

        // load 3rd page
        pagedList.loadAround(if (placeholdersEnabled) 60 else 0)
        drain()
        verifyRange(40, 60, pagedList)
        verifyCallback(callback, 40, 0)
        verifyNoMoreInteractions(callback)
        reset(callback)

        // load 2nd page, drop 5th
        pagedList.loadAround(if (placeholdersEnabled) 40 else 0)
        drain()
        verifyRange(20, 60, pagedList)
        verifyCallback(callback, 20, 0)
        verifyDropCallback(callback, 80, 60)
        verifyNoMoreInteractions(callback)
    }

    @Test
    fun pageDropCancelPrepend() {
        // verify that, based on most recent load position, a prepend can be dropped as it arrives
        val pagedList = createCountedPagedList(
            initialPosition = 2,
            pageSize = 1,
            initLoadSize = 1,
            prefetchDistance = 1,
            maxSize = 3
        )

        // load 3 pages - 2nd, 3rd, 4th
        pagedList.loadAround(if (placeholdersEnabled) 2 else 0)
        drain()
        verifyRange(1, 3, pagedList)

        val callback = mock<Callback>()
        pagedList.addWeakCallback(callback)

        // start a load at the beginning...
        pagedList.loadAround(if (placeholdersEnabled) 1 else 0)

        backgroundThread.executeAll()

        // but before page received, access near end of list
        pagedList.loadAround(if (placeholdersEnabled) 3 else 2)
        verifyZeroInteractions(callback)
        mainThread.executeAll()
        // and the load at the beginning is dropped without signaling callback
        verifyNoMoreInteractions(callback)
        verifyRange(1, 3, pagedList)

        drain()
        if (placeholdersEnabled) {
            verify(callback).onChanged(4, 1)
            verify(callback).onChanged(1, 1)
        } else {
            verify(callback).onInserted(3, 1)
            verify(callback).onRemoved(0, 1)
        }
        verifyRange(2, 3, pagedList)
    }

    @Test
    fun pageDropCancelAppend() {
        // verify that, based on most recent load position, an append can be dropped as it arrives
        val pagedList = createCountedPagedList(
            initialPosition = 2,
            pageSize = 1,
            initLoadSize = 1,
            prefetchDistance = 1,
            maxSize = 3
        )

        // load 3 pages - 2nd, 3rd, 4th
        pagedList.loadAround(if (placeholdersEnabled) 2 else 0)
        drain()

        val callback = mock<Callback>()
        pagedList.addWeakCallback(callback)

        // start a load at the end...
        pagedList.loadAround(if (placeholdersEnabled) 3 else 2)

        backgroundThread.executeAll()

        // but before page received, access near front of list
        pagedList.loadAround(if (placeholdersEnabled) 1 else 0)
        verifyZeroInteractions(callback)
        mainThread.executeAll()
        // and the load at the end is dropped without signaling callback
        verifyNoMoreInteractions(callback)
        verifyRange(1, 3, pagedList)

        drain()
        if (placeholdersEnabled) {
            verify(callback).onChanged(0, 1)
            verify(callback).onChanged(3, 1)
        } else {
            verify(callback).onInserted(0, 1)
            verify(callback).onRemoved(3, 1)
        }
        verifyRange(0, 3, pagedList)
    }

    @Test
    fun loadingListenerAppend() {
        val pagedList = createCountedPagedList(0)
        val capture = pagedList.addLoadStateCapture(LoadType.END)
        val states = capture.second

        // No loading going on currently
        assertEquals(
            listOf(StateChange(LoadType.END, LoadState.Idle)),
            states.getAllAndClear()
        )
        verifyRange(0, 40, pagedList)

        // trigger load
        pagedList.loadAround(35)
        mainThread.executeAll()
        assertEquals(
            listOf(StateChange(LoadType.END, LoadState.Loading)),
            states.getAllAndClear()
        )
        verifyRange(0, 40, pagedList)

        // load finishes
        drain()
        assertEquals(
            listOf(StateChange(LoadType.END, LoadState.Idle)),
            states.getAllAndClear()
        )
        verifyRange(0, 60, pagedList)

        pagedList.pagingSource.enqueueErrorForIndex(65)

        // trigger load which will error
        pagedList.loadAround(55)
        mainThread.executeAll()
        assertEquals(
            listOf(StateChange(LoadType.END, LoadState.Loading)),
            states.getAllAndClear()
        )
        verifyRange(0, 60, pagedList)

        // load now in error state
        drain()
        assertEquals(
            listOf(StateChange(LoadType.END, LoadState.Error(EXCEPTION))),
            states.getAllAndClear()
        )
        verifyRange(0, 60, pagedList)

        // retry
        pagedList.retry()
        mainThread.executeAll()
        assertEquals(
            listOf(StateChange(LoadType.END, LoadState.Loading)),
            states.getAllAndClear()
        )

        // load finishes
        drain()
        assertEquals(
            listOf(StateChange(LoadType.END, LoadState.Idle)),
            states.getAllAndClear()
        )
        verifyRange(0, 80, pagedList)
    }

    @Test
    fun pageDropCancelPrependError() {
        // verify a prepend in error state can be dropped
        val pagedList = createCountedPagedList(
            initialPosition = 2,
            pageSize = 1,
            initLoadSize = 1,
            prefetchDistance = 1,
            maxSize = 3
        )
        val capture = pagedList.addLoadStateCapture(LoadType.START)
        val states = capture.second

        // load 3 pages - 2nd, 3rd, 4th
        pagedList.loadAround(if (placeholdersEnabled) 2 else 0)
        drain()
        verifyRange(1, 3, pagedList)
        assertEquals(
            listOf(
                StateChange(LoadType.START, LoadState.Idle),
                StateChange(LoadType.START, LoadState.Loading),
                StateChange(LoadType.START, LoadState.Idle)
            ),
            states.getAllAndClear()
        )

        // start a load at the beginning, which will fail
        pagedList.pagingSource.enqueueErrorForIndex(0)
        pagedList.loadAround(if (placeholdersEnabled) 1 else 0)
        drain()
        verifyRange(1, 3, pagedList)
        assertEquals(
            listOf(
                StateChange(LoadType.START, LoadState.Loading),
                StateChange(LoadType.START, LoadState.Error(EXCEPTION))
            ),
            states.getAllAndClear()
        )

        // but without that failure being retried, access near end of list, which drops the error
        pagedList.loadAround(if (placeholdersEnabled) 3 else 2)
        drain()
        assertEquals(
            listOf(StateChange(LoadType.START, LoadState.Idle)),
            states.getAllAndClear()
        )
        verifyRange(2, 3, pagedList)
    }

    @Test
    fun pageDropCancelAppendError() {
        // verify an append in error state can be dropped
        val pagedList = createCountedPagedList(
            initialPosition = 2,
            pageSize = 1,
            initLoadSize = 1,
            prefetchDistance = 1,
            maxSize = 3
        )
        val capture = pagedList.addLoadStateCapture(LoadType.END)
        val states = capture.second

        // load 3 pages - 2nd, 3rd, 4th
        pagedList.loadAround(if (placeholdersEnabled) 2 else 0)
        drain()
        verifyRange(1, 3, pagedList)
        assertEquals(
            listOf(
                StateChange(LoadType.END, LoadState.Idle),
                StateChange(LoadType.END, LoadState.Loading),
                StateChange(LoadType.END, LoadState.Idle)
            ),
            states.getAllAndClear()
        )

        // start a load at the end, which will fail
        pagedList.pagingSource.enqueueErrorForIndex(4)
        pagedList.loadAround(if (placeholdersEnabled) 3 else 2)
        drain()
        verifyRange(1, 3, pagedList)
        assertEquals(
            listOf(
                StateChange(LoadType.END, LoadState.Loading),
                StateChange(LoadType.END, LoadState.Error(EXCEPTION))
            ),
            states.getAllAndClear()
        )

        // but without that failure being retried, access near start of list, which drops the error
        pagedList.loadAround(if (placeholdersEnabled) 1 else 0)
        drain()
        assertEquals(
            listOf(StateChange(LoadType.END, LoadState.Idle)),
            states.getAllAndClear()
        )
        verifyRange(0, 3, pagedList)
    }

    @Test
    fun errorIntoDrop() {
        // have an error, move loading range, error goes away
        val pagedList = createCountedPagedList(0)
        val capture = pagedList.addLoadStateCapture(LoadType.END)
        val states = capture.second

        pagedList.pagingSource.enqueueErrorForIndex(45)
        pagedList.loadAround(35)
        drain()
        assertEquals(
            listOf(
                StateChange(LoadType.END, LoadState.Idle),
                StateChange(LoadType.END, LoadState.Loading),
                StateChange(LoadType.END, LoadState.Error(EXCEPTION))
            ),
            states.getAllAndClear()
        )
        verifyRange(0, 40, pagedList)
    }

    @Test
    fun distantPrefetch() {
        val pagedList = createCountedPagedList(
            0,
            initLoadSize = 10,
            pageSize = 10,
            prefetchDistance = 30
        )

        val callback = mock<Callback>()
        pagedList.addWeakCallback(callback)
        verifyRange(0, 10, pagedList)
        verifyZeroInteractions(callback)

        pagedList.loadAround(5)
        drain()

        verifyRange(0, 40, pagedList)

        pagedList.loadAround(6)
        drain()

        // although our prefetch window moves forward, no new load triggered
        verifyRange(0, 40, pagedList)
    }

    @Test
    fun appendCallbackAddedLate() {
        val pagedList = createCountedPagedList(0)
        verifyRange(0, 40, pagedList)

        pagedList.loadAround(35)
        drain()
        verifyRange(0, 60, pagedList)

        // snapshot at 60 items
        val snapshot = pagedList.snapshot() as PagedList<Item>
        val snapshotCopy = snapshot.toList()
        verifyRange(0, 60, snapshot)

        // load more items...
        pagedList.loadAround(55)
        drain()
        verifyRange(0, 80, pagedList)
        verifyRange(0, 60, snapshot)

        // and verify the snapshot hasn't received them
        assertEquals(snapshotCopy, snapshot)
        val callback = mock<Callback>()
        @Suppress("DEPRECATION")
        pagedList.addWeakCallback(snapshot, callback)
        verify(callback).onChanged(0, snapshot.size)
        if (!placeholdersEnabled) {
            verify(callback).onInserted(60, 20)
        }
        verifyNoMoreInteractions(callback)
    }

    @Test
    fun prependCallbackAddedLate() {
        val pagedList = createCountedPagedList(80)
        verifyRange(60, 40, pagedList)

        pagedList.loadAround(if (placeholdersEnabled) 65 else 5)
        drain()
        verifyRange(40, 60, pagedList)

        // snapshot at 60 items
        val snapshot = pagedList.snapshot() as PagedList<Item>
        val snapshotCopy = snapshot.toList()
        verifyRange(40, 60, snapshot)

        pagedList.loadAround(if (placeholdersEnabled) 45 else 5)
        drain()
        verifyRange(20, 80, pagedList)
        verifyRange(40, 60, snapshot)

        assertEquals(snapshotCopy, snapshot)
        val callback = mock<Callback>()
        @Suppress("DEPRECATION")
        pagedList.addWeakCallback(snapshot, callback)
        verify(callback).onChanged(0, snapshot.size)
        if (!placeholdersEnabled) {
            // deprecated snapshot compare dispatches as if inserts occur at the end
            verify(callback).onInserted(60, 20)
        }
        verifyNoMoreInteractions(callback)
    }

    @Test
    fun initialLoad_lastKey() {
        val pagedList = createCountedPagedList(
            initialPosition = 4,
            initLoadSize = 20,
            pageSize = 10
        )
        verifyRange(0, 20, pagedList)

        // lastKey should return result of PagingSource.getRefreshKey after loading 20 items.
        assertEquals(10, pagedList.lastKey)

        // but in practice will be immediately overridden by quick loadAround call
        // (e.g. in latching list after diffing, we loadAround immediately, since previous pos of
        // viewport should win overall)
        pagedList.loadAround(4)
        assertEquals(4, pagedList.lastKey)
    }

    @Test
    fun addWeakCallbackLegacyEmpty() {
        val pagedList = createCountedPagedList(0)
        verifyRange(0, 40, pagedList)

        // capture empty snapshot
        val initSnapshot = pagedList.snapshot()
        assertEquals(pagedList, initSnapshot)

        // verify that adding callback notifies naive "everything changed" when snapshot passed
        var callback = mock<Callback>()
        @Suppress("DEPRECATION")
        pagedList.addWeakCallback(initSnapshot, callback)
        verify(callback).onChanged(0, pagedList.size)
        verifyNoMoreInteractions(callback)
        pagedList.removeWeakCallback(callback)

        pagedList.loadAround(35)
        drain()
        verifyRange(0, 60, pagedList)

        // verify that adding callback notifies insert going from empty -> content
        callback = mock()
        @Suppress("DEPRECATION")
        pagedList.addWeakCallback(initSnapshot, callback)
        verify(callback).onChanged(0, initSnapshot.size)
        if (!placeholdersEnabled) {
            verify(callback).onInserted(40, 20)
        }
        verifyNoMoreInteractions(callback)
    }

    @Test
    fun boundaryCallback_empty() {
        @Suppress("UNCHECKED_CAST")
        val boundaryCallback = mock<BoundaryCallback<Item>>()
        val pagedList = createCountedPagedList(
            0,
            listData = ArrayList(), boundaryCallback = boundaryCallback
        )
        assertEquals(0, pagedList.size)

        // nothing yet
        verifyNoMoreInteractions(boundaryCallback)

        // onZeroItemsLoaded posted, since creation often happens on BG thread
        drain()
        verify(boundaryCallback).onZeroItemsLoaded()
        verifyNoMoreInteractions(boundaryCallback)
    }

    @Test
    fun boundaryCallback_singleInitialLoad() {
        val shortList = ITEMS.subList(0, 4)

        @Suppress("UNCHECKED_CAST")
        val boundaryCallback = mock<BoundaryCallback<Item>>()
        val pagedList = createCountedPagedList(
            0, listData = shortList,
            initLoadSize = shortList.size, boundaryCallback = boundaryCallback
        )
        assertEquals(shortList.size, pagedList.size)

        // nothing yet
        verifyNoMoreInteractions(boundaryCallback)

        // onItemAtFrontLoaded / onItemAtEndLoaded posted, since creation often happens on BG thread
        drain()
        pagedList.loadAround(0)
        drain()
        verify(boundaryCallback).onItemAtFrontLoaded(shortList.first())
        verify(boundaryCallback).onItemAtEndLoaded(shortList.last())
        verifyNoMoreInteractions(boundaryCallback)
    }

    @Test
    fun boundaryCallback_delayed() {
        @Suppress("UNCHECKED_CAST")
        val boundaryCallback = mock<BoundaryCallback<Item>>()
        val pagedList = createCountedPagedList(
            90,
            initLoadSize = 20, prefetchDistance = 5, boundaryCallback = boundaryCallback
        )
        verifyRange(80, 20, pagedList)

        // nothing yet
        verifyZeroInteractions(boundaryCallback)
        drain()
        verifyZeroInteractions(boundaryCallback)

        // loading around last item causes onItemAtEndLoaded
        pagedList.loadAround(if (placeholdersEnabled) 99 else 19)
        drain()
        verifyRange(80, 20, pagedList)
        verify(boundaryCallback).onItemAtEndLoaded(ITEMS.last())
        verifyNoMoreInteractions(boundaryCallback)

        // prepending doesn't trigger callback...
        pagedList.loadAround(if (placeholdersEnabled) 80 else 0)
        drain()
        verifyRange(60, 40, pagedList)
        verifyZeroInteractions(boundaryCallback)

        // ...load rest of data, still no dispatch...
        pagedList.loadAround(if (placeholdersEnabled) 60 else 0)
        drain()
        pagedList.loadAround(if (placeholdersEnabled) 40 else 0)
        drain()
        pagedList.loadAround(if (placeholdersEnabled) 20 else 0)
        drain()
        verifyRange(0, 100, pagedList)
        verifyZeroInteractions(boundaryCallback)

        // ... finally try prepend, see 0 items, which will dispatch front callback
        pagedList.loadAround(0)
        drain()
        verify(boundaryCallback).onItemAtFrontLoaded(ITEMS.first())
        verifyNoMoreInteractions(boundaryCallback)
    }

    private fun drain() {
        while (backgroundThread.queue.isNotEmpty() || mainThread.queue.isNotEmpty()) {
            backgroundThread.executeAll()
            mainThread.executeAll()
        }
    }

    companion object {
        @JvmStatic
        @Parameterized.Parameters(name = "counted:{0}")
        fun parameters(): Array<Array<Boolean>> {
            return arrayOf(arrayOf(true), arrayOf(false))
        }

        val EXCEPTION = Exception()

        private val ITEMS = List(100) { Item(it) }
    }
}
