package com.kennyc.adapters;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by kcampagna on 5/29/15.
 */
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    protected final String TAG = getClass().getSimpleName();

    private List<T> mItems;

    protected LayoutInflater mInflater;

    /**
     * Simple constructor for creating a BaseRecyclerAdapter
     *
     * @param context    The context the adapter is running in
     * @param collection A list of items to populate the adapter with, can be null. If passing a null list,
     *                   {@link #addItem(Object)} will throw an exception as the list type is undefined. The list
     *                   needs to be created first with {@link #addItems(List)}
     */
    public BaseRecyclerAdapter(Context context, List<T> collection) {
        mItems = collection;
        mInflater = LayoutInflater.from(context);
    }

    /**
     * Adds an item to the list, {@link #notifyDataSetChanged()} will be called
     *
     * @param object Object to add to the adapter
     */
    public void addItem(T object) {
        // An exception is thrown instead of creating a List object since the type of list in unknown
        if (mItems == null) throw new NullPointerException("Adapter list has not been initialized");
        mItems.add(object);
        notifyItemInserted(mItems.size());
    }

    /**
     * Adds a list of items to the adapter list, {@link #notifyDataSetChanged()} will be called
     *
     * @param items List of items to add to the adapter
     */
    public void addItems(List<T> items) {
        if (items == null || items.isEmpty()) {
            return;
        }

        int startingSize = 0;
        int endSize = 0;

        if (mItems == null) {
            mItems = items;
        } else {
            startingSize = mItems.size();
            mItems.addAll(items);
        }

        endSize = mItems.size();
        notifyItemRangeInserted(startingSize, endSize);
    }

    /**
     * Removes an object from the list
     *
     * @param object The object to remove from the adapter
     * @return If the object was removed
     */
    public boolean removeItem(T object) {
        if (mItems != null) {
            int position = mItems.indexOf(object);
            return position >= 0 && removeItem(position) != null;
        }

        return false;
    }

    /**
     * Removes an item at the given position, {@link #notifyDataSetChanged()} will be called
     *
     * @param position The position to remove from the adapter
     * @return The item removed
     */
    public T removeItem(int position) {
        if (mItems != null) {
            T removedItem = mItems.remove(position);
            notifyItemRemoved(position);
            return removedItem;
        }

        return null;
    }

    /**
     * Removes all items from the list, {@link #notifyDataSetChanged()} will be called
     */
    public void clear() {
        if (mItems != null) {
            int size = mItems.size();
            mItems.clear();
            notifyItemRangeRemoved(0, size);
        }
    }

    /**
     * Returns the entire list. This is <b><i>not</i></b> a copy of the list. If a copy of the list is
     * needed, see {@link #retainItems()}
     *
     * @return The entire list of items in the adapter
     */
    protected List<T> getAllItems() {
        return mItems;
    }

    /**
     * Returns the object for the given position
     *
     * @param position The position to return
     * @return The item at the given position
     */
    public T getItem(int position) {
        return mItems.get(position);
    }

    /**
     * Returns an ArrayList of the items in the adapter, used for saving the items for configuration changes
     *
     * @return A copy of the items in the adapter
     */
    public ArrayList<T> retainItems() {
        return new ArrayList<>(mItems);
    }

    @Override
    public int getItemCount() {
        return mItems != null ? mItems.size() : 0;
    }

    /**
     * Returns if the adapter is empty
     *
     * @return If the adapter is empty
     */
    public boolean isEmpty() {
        return mItems == null || mItems.size() <= 0;
    }
}

@@ -336,17 +336,16 @@
 lder%3E %7B%0A
-%0A
     prot
@@ -1124,39 +1124,50 @@
 link #notify
-DataSetChanged(
+ItemRangeInserted(int, int
 )%7D will be c
@@ -1621,39 +1621,50 @@
 link #notify
-DataSetChanged(
+ItemRangeInserted(int, int
 )%7D will be c
@@ -2194,39 +2194,629 @@
   * 
-Removes an object from the list
+Adds a list of items to the adapter list at the given position, %7B@link #notifyItemRangeInserted(int, int)%7D will be called%0A     *%0A     * @param items    List of items to add to the adapter%0A     * @param position The position to add the items into the adapter%0A     */%0A    public void addItems(List%3CT%3E items, int position) %7B%0A        if (items == null %7C%7C items.isEmpty()) %7B%0A            return;%0A        %7D%0A%0A        mItems.addAll(position, items);%0A        notifyItemRangeInserted(position, items.size());%0A    %7D%0A%0A    /**%0A     * Removes an object from the list, %7B@link #notifyItemRangeRemoved(int, int)%7D (int, int)%7D will be called
 %0A   
@@ -3220,39 +3220,39 @@
 link #notify
-DataSetChanged(
+ItemRemoved(int
 )%7D will be c
@@ -3594,32 +3594,411 @@
 rn null;%0A    %7D%0A%0A
+    /**%0A     * Removes a range of items from the adapter, %7B@link #notifyItemRangeRemoved(int, int)%7D will be called%0A     *%0A     * @param start Starting position of removal%0A     * @param end   Ending position of removal%0A     */%0A    public void removeItems(int start, int end) %7B%0A        mItems.subList(start, end).clear();%0A        notifyItemRangeRemoved(start, end - start);%0A    %7D%0A%0A
     /**%0A     * R
@@ -4047,23 +4047,33 @@
 tify
-DataSetChanged(
+ItemRangeRemoved(int, int
 )%7D w
@@ -5338,37 +5338,20 @@
 urn 
-m
+get
 Item
-s == null %7C%7C mItems.size
+Count
 () %3C

Add Additional Add/Remove Methods