/*
 * 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.
 */

package androidx.paging

import androidx.recyclerview.widget.AdapterListUpdateCallback
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.MergeAdapter
import androidx.recyclerview.widget.RecyclerView

/**
 * [RecyclerView.Adapter] base class for presenting paged data from [androidx.paging.PagedList]s in
 * a [RecyclerView].
 *
 * This class is a convenience wrapper around [AsyncPagedListDiffer] that implements common default
 * behavior for item counting, and listening to PagedList update callbacks.
 *
 * While using a LiveData<PagedList> is an easy way to provide data to the adapter, it isn't
 * required - you can use [submitList] when new lists are available.
 *
 * PagedListAdapter listens to PagedList loading callbacks as pages are loaded, and uses DiffUtil on
 * a background thread to compute fine grained updates as new PagedLists are received.
 *
 * Handles both the internal paging of the list as more data is loaded, and updates in the form of
 * new PagedLists.
 *
 * A complete usage pattern with Room would look like this:
 * ```
 * @Dao
 * interface UserDao {
 *     @Query("SELECT * FROM user ORDER BY lastName ASC")
 *     public abstract DataSource.Factory<Integer, User> usersByLastName();
 * }
 *
 * class MyViewModel extends ViewModel {
 *     public final LiveData<PagedList<User>> usersList;
 *     public MyViewModel(UserDao userDao) {
 *         usersList = new LivePagedListBuilder&lt;>(
 *         userDao.usersByLastName(), /* page size */ 20).build();
 *     }
 * }
 *
 * class MyActivity extends AppCompatActivity {
 *     @Override
 *     public void onCreate(Bundle savedState) {
 *         super.onCreate(savedState);
 *         MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
 *         RecyclerView recyclerView = findViewById(R.id.user_list);
 *         UserAdapter&lt;User> adapter = new UserAdapter();
 *         viewModel.usersList.observe(this, pagedList -> adapter.submitList(pagedList));
 *         recyclerView.setAdapter(adapter);
 *     }
 * }
 *
 * class UserAdapter extends PagedListAdapter<User, UserViewHolder> {
 *     public UserAdapter() {
 *         super(DIFF_CALLBACK);
 *     }
 *     @Override
 *     public void onBindViewHolder(UserViewHolder holder, int position) {
 *         User user = getItem(position);
 *         if (user != null) {
 *             holder.bindTo(user);
 *         } else {
 *             // Null defines a placeholder item - PagedListAdapter will automatically invalidate
 *             // this row when the actual object is loaded from the database
 *             holder.clear();
 *         }
 *     }
 *     public static final DiffUtil.ItemCallback&lt;User> DIFF_CALLBACK =
 *             new DiffUtil.ItemCallback<User>() {
 *         @Override
 *         public boolean areItemsTheSame(@NonNull User oldUser, @NonNull User newUser) {
 *             // User properties may have changed if reloaded from the DB, but ID is fixed
 *             return oldUser.getId() == newUser.getId();
 *         }
 *         @Override
 *         public boolean areContentsTheSame(@NonNull User oldUser, @NonNull User newUser) {
 *             // NOTE: if you use equals, your object must properly override Object#equals()
 *             // Incorrectly returning false here will result in too many animations.
 *             return oldUser.equals(newUser);
 *         }
 *     }
 * }
 * ```
 *
 * Advanced users that wish for more control over adapter behavior, or to provide a specific base
 * class should refer to [AsyncPagedListDiffer], which provides the mapping from paging
 * events to adapter-friendly callbacks.
 *
 * @param T Type of the PagedLists this Adapter will receive.
 * @param VH A class that extends ViewHolder that will be used by the adapter.
 */
@Deprecated(
    message = "PagedListAdapter is deprecated and has been replaced by PagingDataAdapter",
    replaceWith = ReplaceWith(
        "PagingDataAdapter<T, VH>",
        "androidx.paging.PagingDataAdapter"
    )
)
abstract class PagedListAdapter<T : Any, VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH> {
    @Suppress("DEPRECATION")
    internal val differ: AsyncPagedListDiffer<T>
    @Suppress("DEPRECATION")
    private val listener = { previousList: PagedList<T>?, currentList: PagedList<T>? ->
        this@PagedListAdapter.onCurrentListChanged(currentList)
        this@PagedListAdapter.onCurrentListChanged(previousList, currentList)
    }

    /**
     * Returns the [PagedList] currently being displayed by the [PagedListAdapter].
     *
     * This is not necessarily the most recent list passed to [submitList], because a diff is
     * computed asynchronously between the new list and the current list before updating the
     * currentList value. May be null if no PagedList is being presented.
     *
     * @return The list currently being displayed.
     *
     * @see onCurrentListChanged
     */
    @Suppress("DEPRECATION")
    open val currentList: PagedList<T>?
        get() = differ.currentList

    /**
     * Creates a [PagedListAdapter] with default threading and
     * [androidx.recyclerview.widget.ListUpdateCallback].
     *
     * Convenience for [PagedListAdapter], which uses default threading behavior.
     *
     * @param diffCallback The [DiffUtil.ItemCallback] instance to
     * compare items in the list.
     */
    protected constructor(diffCallback: DiffUtil.ItemCallback<T>) {
        @Suppress("DEPRECATION")
        differ = AsyncPagedListDiffer(this, diffCallback)
        differ.addPagedListListener(listener)
    }

    protected constructor(config: AsyncDifferConfig<T>) {
        @Suppress("DEPRECATION")
        differ = AsyncPagedListDiffer(AdapterListUpdateCallback(this), config)
        differ.addPagedListListener(listener)
    }

    /**
     * Set the new list to be displayed.
     *
     * If a list is already being displayed, a diff will be computed on a background thread, which
     * will dispatch Adapter.notifyItem events on the main thread.
     *
     * @param pagedList The new list to be displayed.
     */
    open fun submitList(@Suppress("DEPRECATION") pagedList: PagedList<T>?) =
        differ.submitList(pagedList)

    /**
     * Set the new list to be displayed.
     *
     * If a list is already being displayed, a diff will be computed on a background thread, which
     * will dispatch Adapter.notifyItem events on the main thread.
     *
     * The commit callback can be used to know when the PagedList is committed, but note that it
     * may not be executed. If PagedList B is submitted immediately after PagedList A, and is
     * committed directly, the callback associated with PagedList A will not be run.
     *
     * @param pagedList The new list to be displayed.
     * @param commitCallback Optional runnable that is executed when the PagedList is committed, if
     * it is committed.
     */
    open fun submitList(
        @Suppress("DEPRECATION") pagedList: PagedList<T>?,
        commitCallback: Runnable?
    ) = differ.submitList(pagedList, commitCallback)

    protected open fun getItem(position: Int) = differ.getItem(position)

    override fun getItemCount() = differ.itemCount

    /**
     * Called when the current PagedList is updated.
     *
     * This may be dispatched as part of [.submitList] if a background diff isn't
     * needed (such as when the first list is passed, or the list is cleared). In either case,
     * PagedListAdapter will simply call
     * [notifyItemRangeInserted/Removed(0, mPreviousSize)][.notifyItemRangeInserted].
     *
     * This method will *not*be called when the Adapter switches from presenting a PagedList
     * to a snapshot version of the PagedList during a diff. This means you cannot observe each
     * PagedList via this method.
     *
     * @param currentList new PagedList being displayed, may be null.
     *
     * @see currentList
     */
    @Deprecated(
        "Use the two argument variant instead.",
        ReplaceWith("onCurrentListChanged(previousList, currentList)")
    )
    open fun onCurrentListChanged(@Suppress("DEPRECATION") currentList: PagedList<T>?) {
    }

    /**
     * Called when the current PagedList is updated.
     *
     * This may be dispatched as part of [.submitList] if a background diff isn't
     * needed (such as when the first list is passed, or the list is cleared). In either case,
     * PagedListAdapter will simply call
     * [notifyItemRangeInserted/Removed(0, mPreviousSize)][notifyItemRangeInserted].
     *
     * This method will *not*be called when the Adapter switches from presenting a PagedList
     * to a snapshot version of the PagedList during a diff. This means you cannot observe each
     * PagedList via this method.
     *
     * @param previousList [PagedList] that was previously displayed, may be null.
     * @param currentList new [PagedList] being displayed, may be null.
     *
     * @see currentList
     */
    open fun onCurrentListChanged(
        @Suppress("DEPRECATION") previousList: PagedList<T>?,
        @Suppress("DEPRECATION") currentList: PagedList<T>?
    ) {
    }

    /**
     * Add a [LoadState] listener to observe the loading state of the current [PagedList].
     *
     * As new PagedLists are submitted and displayed, the listener will be notified to reflect
     * current [LoadType.REFRESH], [LoadType.START], and [LoadType.END] states.
     *
     * @param listener [LoadStateListener] to receive updates.
     *
     * @see removeLoadStateListener
     */
    open fun addLoadStateListener(listener: (LoadType, LoadState) -> Unit) {
        differ.addLoadStateListener(listener)
    }

    /**
     * Remove a previously registered [LoadState] listener.
     *
     * @param listener Previously registered listener.
     * @see addLoadStateListener
     */
    open fun removeLoadStateListener(listener: (LoadType, LoadState) -> Unit) {
        differ.removeLoadStateListener(listener)
    }

    /**
     * Create a [MergeAdapter] with the provided [LoadStateAdapter]s displaying the
     * [LoadType.END] [LoadState] as a list item at the end of the presented list.
     */
    fun withLoadStateHeader(
        header: LoadStateAdapter<*>
    ): MergeAdapter {
        addLoadStateListener { loadType, loadState ->
            if (loadType == LoadType.START) {
                header.loadState = loadState
            }
        }
        return MergeAdapter(header, this)
    }

    /**
     * Create a [MergeAdapter] with the provided [LoadStateAdapter]s displaying the
     * [LoadType.START] [LoadState] as a list item at the start of the presented list.
     */
    fun withLoadStateFooter(
        footer: LoadStateAdapter<*>
    ): MergeAdapter {
        addLoadStateListener { loadType, loadState ->
            if (loadType == LoadType.END) {
                footer.loadState = loadState
            }
        }
        return MergeAdapter(this, footer)
    }

    /**
     * Create a [MergeAdapter] with the provided [LoadStateAdapter]s displaying the
     * [LoadType.START] and [LoadType.END] [LoadState]s as list items at the start and end
     * respectively.
     */
    fun withLoadStateHeaderAndFooter(
        header: LoadStateAdapter<*>,
        footer: LoadStateAdapter<*>
    ): MergeAdapter {
        addLoadStateListener { loadType, loadState ->
            if (loadType == LoadType.START) {
                header.loadState = loadState
            } else if (loadType == LoadType.END) {
                footer.loadState = loadState
            }
        }
        return MergeAdapter(header, this, footer)
    }
}
