package com.marshalchen.ultimaterecyclerview;


import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;

import com.marshalchen.ultimaterecyclerview.multiViewTypes.DataBinder;
import java.util.HashMap;
import java.util.Map;

/**
 * An abstract adapter which can be extended for Recyclerview
 */
public abstract class UltimateDifferentViewTypeAdapter<E extends Enum<E>>  extends UltimateViewAdapter {
    private Map<E, DataBinder> mBinderMap = new HashMap<>();

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return getDataBinder(viewType).newViewHolder(parent);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
        int binderPosition = getBinderPosition(position);
        getDataBinder(viewHolder.getItemViewType()).bindViewHolder(viewHolder, binderPosition);
    }

    @Override
    public int getItemCount() {
        int itemCount = 0;
        for (DataBinder binder : mBinderMap.values()) {
            itemCount += binder.getItemCount();
        }
        return itemCount;
    }

    @Override
    public int getItemViewType(int position) {
        return getEnumFromPosition(position).ordinal();
    }

    public <T extends DataBinder> T getDataBinder(int viewType) {
        return getDataBinder(getEnumFromOrdinal(viewType));
    }

    public int getPosition(DataBinder binder, int binderPosition) {
        E targetViewType = getEnumFromBinder(binder);
        for (int i = 0; i < getItemCount(); i++) {
            if (targetViewType == getEnumFromPosition(i)) {
                binderPosition--;
                if (binderPosition <= 0) {
                    return i;
                }
            }
        }
        return getItemCount();
    }

    public int getBinderPosition(int position) {
        E targetViewType = getEnumFromPosition(position);
        int binderPosition = -1;
        for (int i = 0; i <= position; i++) {
            if (targetViewType == getEnumFromPosition(i)) {
                binderPosition++;
            }
        }

        if (binderPosition == -1) {
            throw new IllegalArgumentException("Invalid Argument");
        }
        return binderPosition;
    }

    public void notifyBinderItemRangeChanged(DataBinder binder, int positionStart, int itemCount) {
        for (int i = positionStart; i <= itemCount; i++) {
            notifyItemChanged(getPosition(binder, i));
        }
    }

    public void notifyBinderItemRangeInserted(DataBinder binder, int positionStart, int itemCount) {
        for (int i = positionStart; i <= itemCount; i++) {
            notifyItemInserted(getPosition(binder, i));
        }
    }

    public void notifyBinderItemRangeRemoved(DataBinder binder, int positionStart, int itemCount) {
        for (int i = positionStart; i <= itemCount; i++) {
            notifyItemRemoved(getPosition(binder, i));
        }
    }

    public void notifyBinderItemChanged(DataBinder binder, int binderPosition) {
        notifyItemChanged(getPosition(binder, binderPosition));
    }


    public void notifyBinderItemInserted(DataBinder binder, int binderPosition) {
        notifyItemInserted(getPosition(binder, binderPosition));
    }

    public void notifyBinderItemMoved(DataBinder binder, int fromPosition, int toPosition) {
        notifyItemMoved(getPosition(binder, fromPosition), getPosition(binder, toPosition));
    }


    public void notifyBinderItemRemoved(DataBinder binder, int binderPosition) {
        notifyItemRemoved(getPosition(binder, binderPosition));
    }




    public abstract E getEnumFromPosition(int position);

    public abstract E getEnumFromOrdinal(int ordinal);

    public E getEnumFromBinder(DataBinder binder) {
        for (Map.Entry<E, DataBinder> entry : mBinderMap.entrySet()) {
            if (entry.getValue().equals(binder)) {
                return entry.getKey();
            }
        }
        throw new IllegalArgumentException("Invalid Data Binder");
    }

    public <T extends DataBinder> T getDataBinder(E e) {
        return (T) mBinderMap.get(e);
    }

    public Map<E, DataBinder> getBinderMap() {
        return mBinderMap;
    }

    public void putBinder(E e, DataBinder binder) {
        mBinderMap.put(e, binder);
    }

    public void removeBinder(E e) {
        mBinderMap.remove(e);
    }

    public void clearBinderMap() {
        mBinderMap.clear();
    }
}

@@ -191,16 +191,17 @@
 Binder;%0A
+%0A
 import j
@@ -384,17 +384,16 @@
 Enum%3CE%3E%3E
- 
  extends
@@ -473,24 +473,152 @@
 shMap%3C%3E();%0A%0A
+    protected class VIEW_TYPES extends UltimateViewAdapter.VIEW_TYPES %7B%0A        public static final int MULTI_VIEWS = 5;%0A    %7D%0A%0A
     @Overrid
@@ -1329,55 +1329,205 @@
     
-return getEnumFromPosition(position).ordinal();
+int type = super.getItemViewType(position);%0A        if (type == VIEW_TYPES.NORMAL) %7B%0A            return getEnumFromPosition(position).ordinal();%0A        %7D else %7B%0A            return type;%0A        %7D%0A
 %0A   
@@ -3889,18 +3889,16 @@
     %7D%0A%0A%0A
-%0A%0A
     publ

change getItemViewType In UltimateDifferentViewTypeAdapter