package ir.coderz.coreadapter;

import android.support.annotation.IntRange;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Created by sajad on 6/30/16.
 */
public class CoreAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    List<CoreItem> items = new ArrayList<>();
    HashMap<Integer, Class<? extends RecyclerView.ViewHolder>> viewTypes = new HashMap<>();
    private LayoutInflater layoutInflater;

    public CoreAdapter(HashMap<Integer, Class<? extends RecyclerView.ViewHolder>> viewTypes) {
        this.viewTypes = viewTypes;
    }

    public CoreAdapter(@LayoutRes int layout, Class<? extends RecyclerView.ViewHolder> holder) {
        this.viewTypes = new HashMap<>();
        this.viewTypes.put(layout, holder);
    }

    public CoreAdapter() {
    }

    public void putViewType(@LayoutRes int layout, Class<? extends RecyclerView.ViewHolder> holder) {
        this.viewTypes.put(layout, holder);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (layoutInflater == null) {
            layoutInflater = LayoutInflater.from(parent.getContext());
        }
        if (viewTypes.size() == 0) {
            throw new IndexOutOfBoundsException(
                    "No ViewType is specified." +
                            "call putViewType before using adapter");
        }
        View view = layoutInflater.inflate(viewType, parent, false);
        try {
            return viewTypes.get(viewType).getConstructor(View.class).newInstance(view);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        items.get(position).bind(holder);
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    @Override
    public int getItemViewType(int position) {
        return items.get(position).getLayout();
    }

    /**
     * @param items CoreAdapter uses these items and bind recycler to them
     */
    public <T extends CoreItem> void setItems(@NonNull List<T> items) {
        this.items.clear();
        this.items.addAll(items);
        notifyDataSetChanged();
    }

    public void removeAll() {
        items.clear();
        notifyDataSetChanged();
    }

    public <T extends CoreItem> void addItems(@NonNull List<T> items) {
        int start = this.items.size() - 1;
        this.items.addAll(items);
        if(start>=0) {
            notifyItemRangeInserted(start, items.size());
        }else {
            notifyDataSetChanged();
        }
    }

    public <T extends CoreItem> void addItems(@IntRange(from = 0) int position, @NonNull List<T> items) {
        if (position > items.size()) {
            throw new IndexOutOfBoundsException();
        }
        this.items.addAll(position, items);
        notifyItemRangeInserted(position, items.size());
    }

    public <T extends CoreItem> void addItem(@NonNull T item) {
        items.add(item);
        notifyItemInserted(items.size() - 1);
    }

    public <T extends CoreItem> void removeItem(@NonNull T item) {
        int index = items.indexOf(item);
        if (index >= 0) {
            items.remove(index);
            notifyItemRemoved(index);
        }


    }

    public void removeRangeOfItems(@IntRange(from = 0)int from,@IntRange int to) {

        if(items.size()>from && items.size()>to){

            for (int i=from;i<to;i++){
                items.remove(i);
            }
            notifyDataSetChanged();

        }
    }


    /**
     * adding an item to a position
     *
     * @param position insert position
     * @param item input item
     */
    public <T extends CoreItem> void addItem(@IntRange(from = 0) int position, @NonNull T item) {
        if (position > items.size()) {
            throw new IndexOutOfBoundsException();
        }
        items.add(position, item);
        notifyItemInserted(position);
    }
}

@@ -2973,32 +2973,107 @@
 anged();%0A    %7D%0A%0A
+    /**%0A     * @param items%0A     * @param %3CT%3E%0A     * @see CoreItem%0A     */%0A
     public %3CT ex
@@ -3219,16 +3219,19 @@
   if
+ 
 (start
+ 
 %3E=
+ 
 0) %7B
@@ -3298,16 +3298,17 @@
        %7D
+ 
 else %7B%0A 
@@ -3665,32 +3665,106 @@
 size());%0A    %7D%0A%0A
+    /**%0A     * @param item%0A     * @param %3CT%3E%0A     * @see CoreItem%0A     */%0A
     public %3CT ex
@@ -3881,32 +3881,124 @@
 () - 1);%0A    %7D%0A%0A
+    /**%0A     * @param item%0A     * @param %3CT%3E  extends CoreItem%0A     * @see CoreItem%0A     */%0A
     public %3CT ex
@@ -4197,32 +4197,113 @@
      %7D%0A%0A%0A    %7D%0A%0A
+    /**%0A     * remove items%0A     *%0A     * @param start%0A     * @param end%0A     */%0A
     public void 
@@ -4312,20 +4312,17 @@
 move
+Item
 Range
-OfItems
 (@In
@@ -4341,17 +4341,20 @@
 = 0)
+ 
 int 
-from,
+start, 
 @Int
@@ -4362,15 +4362,26 @@
 ange
+(from = 0)
  int 
-to
+end
 ) %7B%0A
@@ -4391,17 +4391,26 @@
       if
-(
+ (start %3C 
 items.si
@@ -4417,16 +4417,17 @@
 ze()
-%3Efrom &&
+ && end %3C
  ite
@@ -4439,12 +4439,10 @@
 ze()
-%3Eto
 )
+ 
 %7B%0A%0A 
@@ -4466,23 +4466,32 @@
 nt i
-=from;i%3Cto;
+ = start; i %3C end; 
 i++)
+ 
 %7B%0A  
@@ -4699,16 +4699,20 @@
 am item 
+    
 input it

add few docs, rename removeRangeOfItems -> removeItemRange