package com.zhaohaoting.framework.mvchelper.recyclerview;

import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.FrameLayout;

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

public abstract class HFAdapter extends RecyclerView.Adapter {

    public static final int TYPE_MANAGER_OTHER = 0;
    public static final int TYPE_MANAGER_LINEAR = 1;
    public static final int TYPE_MANAGER_GRID = 2;
    public static final int TYPE_MANAGER_STAGGERED_GRID = 3;

    public static final int TYPE_HEADER = 7898;
    public static final int TYPE_FOOTER = 7899;

    private List<View> mHeaders = new ArrayList<View>();
    private List<View> mFooters = new ArrayList<View>();
    private boolean needSetClickListener = true;

    public HFAdapter() {
        this(true);
    }

    public HFAdapter(boolean needSetClickListener) {
        this.needSetClickListener = needSetClickListener;
    }

    private int mManagerType;

    public int getHeadSize() {
        return mHeaders.size();
    }

    public int getFootSize() {
        return mFooters.size();
    }

    public int getManagerType() {
        return mManagerType;
    }

    public void notifyDataSetChangedHF() {
        notifyDataSetChanged();
    }

    public void notifyItemChangedHF(int position) {
        notifyItemChanged(getRealPosition(position));
    }

    public void notifyItemMovedHF(int fromPosition, int toPosition) {
        notifyItemMoved(getRealPosition(fromPosition), getRealPosition(toPosition));
    }

    public void notifyItemRangeChangedHF(int positionStart, int itemCount) {
        notifyItemRangeChanged(getRealPosition(positionStart), itemCount);
    }

    public void notifyItemRangeRemovedHF(int positionStart, int itemCount) {
        notifyItemRangeRemoved(getRealPosition(positionStart), itemCount);
    }

    public void notifyItemRemovedHF(int position) {
        notifyItemRemoved(getRealPosition(position));
    }

    public void notifyItemInsertedHF(int position) {
        notifyItemInserted(getRealPosition(position));
    }

    public void notifyItemRangeInsertedHF(int positionStart, int itemCount) {
        notifyItemRangeInserted(getRealPosition(positionStart), itemCount);
    }

    @Override
    public final long getItemId(int position) {
        return getItemIdHF(getRealPosition(position));
    }

    public long getItemIdHF(int position) {
        return super.getItemId(position);
    }

    public abstract ViewHolder onCreateViewHolderHF(ViewGroup viewGroup, int type);

    @Override
    public final ViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
        // if our position is one of our items (this comes from
        // getItemViewType(int position) below)
        if (type != TYPE_HEADER && type != TYPE_FOOTER) {
            ViewHolder vh = onCreateViewHolderHF(viewGroup, type);
            return vh;
            // else we have a header/footer
        } else {
            // createExecutor a new framelayout, or inflate from a resource
            FrameLayout frameLayout = new FrameLayout(viewGroup.getContext());
            // make sure it fills the space
            frameLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            return new HeaderFooterViewHolder(frameLayout);
        }
    }

    @Override
    public final void onBindViewHolder(final ViewHolder vh, int position) {
        // check what type of view our position is
        if (isHeader(position)) {
            View v = mHeaders.get(position);
            // add our view to a header view and display it
            prepareHeaderFooter((HeaderFooterViewHolder) vh, v);
        } else if (isFooter(position)) {
            View v = mFooters.get(position - getItemCountHF() - mHeaders.size());
            // add our view to a footer view and display it
            prepareHeaderFooter((HeaderFooterViewHolder) vh, v);
        } else {
            if (needSetClickListener) {
                vh.itemView.setOnClickListener(new MyOnClickListener(vh));
                vh.itemView.setOnLongClickListener(new MyOnLongClickListener(vh));
            }
            // it's one of our items, display as required
            onBindViewHolderHF(vh, getRealPosition(position));
        }
    }

    /**
     * 处理当时Gridview类型的效果时，也把头部和尾部设置成一整行（这就是RecyclerView的其中一个优秀之处，列表的每行可以不同数量的列）
     *
     * @param recyclerView
     */
    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            GridLayoutManager.SpanSizeLookup spanSizeLookup = ((GridLayoutManager) layoutManager).getSpanSizeLookup();
            ((GridLayoutManager) layoutManager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    int itemViewType = getItemViewType(position);
                    int size;
                    if (itemViewType == TYPE_HEADER || itemViewType == TYPE_FOOTER) {
                        size = ((GridLayoutManager) layoutManager).getSpanCount();
                    } else {
                        size = spanSizeLookup.getSpanSize(position);
                    }
                    return size;
                }
            });
        }
    }

    @Override
    public final void onBindViewHolder(ViewHolder holder, int position, List payloads) {
        super.onBindViewHolder(holder, position, payloads);
    }

    public int getRealPosition(int position) {
        return position - mHeaders.size();
    }

    public abstract void onBindViewHolderHF(ViewHolder vh, int position);

    private boolean isHeader(int position) {
        return (position < mHeaders.size());
    }

    public boolean isHeader(ViewHolder viewHolder) {
        return isHeader(viewHolder.getAdapterPosition());
    }

    public boolean isFooter(ViewHolder viewHolder) {
        return isFooter(viewHolder.getAdapterPosition());
    }


    private void prepareHeaderFooter(HeaderFooterViewHolder vh, View view) {

        // if it's a staggered grid, span the whole layout
        if (mManagerType == TYPE_MANAGER_STAGGERED_GRID) {
            StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
            layoutParams.setFullSpan(true);
            vh.itemView.setLayoutParams(layoutParams);
        }

        // if the view already belongs to another layout, remove it
        if (view.getParent() != null) {
            ((ViewGroup) view.getParent()).removeView(view);
        }

        // empty out our FrameLayout and replace with our header/footer
        vh.base.removeAllViews();
        vh.base.addView(view);

    }

    private boolean isFooter(int position) {
        return (position >= mHeaders.size() + getItemCountHF());
    }

    @Override
    public final int getItemCount() {
        return mHeaders.size() + getItemCountHF() + mFooters.size();
    }

    public abstract int getItemCountHF();

    @Override
    public final int getItemViewType(int position) {
        // check what type our position is, based on the assumption that the
        // order is headers > items > footers
        if (isHeader(position)) {
            return TYPE_HEADER;
        } else if (isFooter(position)) {
            return TYPE_FOOTER;
        }
        int type = getItemViewTypeHF(getRealPosition(position));
        if (type == TYPE_HEADER || type == TYPE_FOOTER) {
            throw new IllegalArgumentException("Item type cannot equal " + TYPE_HEADER + " or " + TYPE_FOOTER);
        }
        return type;
    }

    public int getItemViewTypeHF(int position) {
        return super.getItemViewType(position);
    }

    // add a header to the adapter
    public void addHeader(View header) {
        if (!mHeaders.contains(header)) {
            mHeaders.add(header);
            // animate
            notifyItemInserted(mHeaders.size() - 1);
        }
    }

    // remove a header from the adapter
    public void removeHeader(View header) {
        if (mHeaders.contains(header)) {
            // animate
            notifyItemRemoved(mHeaders.indexOf(header));
            mHeaders.remove(header);
        }
    }

    // add a footer to the adapter
    public void addFooter(View footer) {
        if (!mFooters.contains(footer)) {
            mFooters.add(footer);
            // animate
            notifyItemInserted(mHeaders.size() + getItemCountHF() + mFooters.size() - 1);
        }
    }

    // remove a footer from the adapter
    public void removeFooter(View footer) {
        if (mFooters.contains(footer)) {
            // animate
            notifyItemRemoved(mHeaders.size() + getItemCountHF() + mFooters.indexOf(footer));
            mFooters.remove(footer);
        }
    }

    // our header/footer RecyclerView.ViewHolder is just a FrameLayout
    public static class HeaderFooterViewHolder extends ViewHolder {
        FrameLayout base;

        public HeaderFooterViewHolder(View itemView) {
            super(itemView);
            base = (FrameLayout) itemView;
        }
    }

    public OnItemClickListener getOnItemClickListener() {
        return onItemClickListener;
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
        Log.d("eeee", "setOnItemClickListener " + this.onItemClickListener);
    }

    public OnItemLongClickListener getOnItemLongClickListener() {
        return onItemLongClickListener;
    }

    public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {
        this.onItemLongClickListener = onItemLongClickListener;
    }

    private OnItemClickListener onItemClickListener;

    private OnItemLongClickListener onItemLongClickListener;

    private class MyOnClickListener implements OnClickListener {
        private ViewHolder vh;

        public MyOnClickListener(ViewHolder vh) {
            super();
            this.vh = vh;
        }

        @Override
        public void onClick(View v) {
            int position = getRealPosition(vh.getLayoutPosition());
            if (!onItemClick(vh, position)) {
                if (HFAdapter.this.onItemClickListener != null) {
                    HFAdapter.this.onItemClickListener.onItemClick(HFAdapter.this, vh, position);
                }
            }
        }
    }

    private class MyOnLongClickListener implements OnLongClickListener {
        private ViewHolder vh;

        public MyOnLongClickListener(ViewHolder vh) {
            super();
            this.vh = vh;
        }

        @Override
        public boolean onLongClick(View v) {
            int position = getRealPosition(vh.getLayoutPosition());
            if (!onItemLongClick(vh, position)) {
                if (HFAdapter.this.onItemLongClickListener != null) {
                    HFAdapter.this.onItemLongClickListener.onItemLongClick(HFAdapter.this, vh, position);
                }
            }
            return true;
        }

    }

    /**
     * 直接在Adapter里面处理项的点击事件
     *
     * @param vh
     * @param position
     * @return 如果返回true，事件就被拦截不再调用onItemClickListener，否则会调用onItemClickListener
     */
    protected boolean onItemClick(ViewHolder vh, int position) {
        return false;
    }

    /**
     * 直接在Adapter里面处理项的长按事件
     *
     * @param vh       ViewHolder
     * @param position item位置
     * @return 如果返回true，事件就被拦截不再调用onItemLongClickListener，否则会调用onItemLongClickListener
     */
    protected boolean onItemLongClick(ViewHolder vh, int position) {
        return false;
    }

    public static interface OnItemClickListener {

        void onItemClick(HFAdapter adapter, ViewHolder vh, int position);

    }

    public static interface OnItemLongClickListener {

        void onItemLongClick(HFAdapter adapter, ViewHolder vh, int position);

    }

    public void setmManagerType(int mManagerType) {
        this.mManagerType = mManagerType;
    }
}
