package com.zhaohaoting.framework.abs.adapter;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.databinding.ViewDataBinding;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

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

/**
 * author：Created by ZHT on 2017/11/23 10:37
 * email：526309416@qq.com
 * desc：RecyclerView 适配器基类  只有此适配器适配了 mvc_helper
 */
@SuppressWarnings("unchecked")
public abstract class AbsRecyclerAdapter<DATA, BASE_DATA> extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements IRecyclerViewDataAdapter<BASE_DATA> {

    protected Context context;
    private List<View> mHeaders = new ArrayList<View>();
    private List<View> mFooters = new ArrayList<View>();
    protected OnItemClickListener onItemClickListener;
    protected OnItemViewClickListener onItemViewClickListener;
    protected OnItemLongClickListener onItemLongClickListener;
    protected LayoutInflater inflater;
    private static final int TYPE_NORMAL = 7895;
    private static final int TYPE_HEADER = 7896;
    private static final int TYPE_FOOTER = 7897;
    protected List<DATA> mDataList;

    public AbsRecyclerAdapter(Context context) {
        this(context, new ArrayList<>());
    }

    public AbsRecyclerAdapter(Context context, List<DATA> dataList) {
        this.context = context;
        inflater = LayoutInflater.from(context);
        if (dataList == null) {
            this.mDataList = new ArrayList<>();
        } else {
            this.mDataList = dataList;
        }
//        Type type = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1];
//        if (type instanceof ParameterizedType) {
//            resultCls = (Class<BASE_DATA>) ((ParameterizedType) type).getRawType();
//        } else {
//            resultCls = (Class<BASE_DATA>) type;
//        }
    }

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

    public int getItemCountHF() {
        return mDataList.size();
    }

    @Override
    public final int getItemViewType(int position) {
        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;
    }

    protected int getItemViewTypeHF(int realPosition) {
        return TYPE_NORMAL;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType != TYPE_HEADER && viewType != TYPE_FOOTER) {
            return onCreateViewHolderHF(parent, viewType);
        } else {
            FrameLayout frameLayout = new FrameLayout(parent.getContext());
            frameLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            return new HeaderFooterViewHolder(frameLayout);
        }
    }

    protected RecyclerView.ViewHolder onCreateViewHolderHF(ViewGroup parent, int viewType) {
        ViewDataBinding dataBinding = DataBindingUtil.inflate(inflater, getItemLayoutId(viewType), parent, false);
        return new BaseViewHolder(dataBinding);
    }

    protected abstract int getItemLayoutId(int type);

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder vh, final int position) {
        if (isHeader(position)) {
            View v = mHeaders.get(position);
            prepareHeaderFooter((HeaderFooterViewHolder) vh, v);
        } else if (isFooter(position)) {
            View v = mFooters.get(position - getItemCountHF() - mHeaders.size());
            prepareHeaderFooter((HeaderFooterViewHolder) vh, v);
        } else {
            final int realPosition = getRealPosition(position);
            vh.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (onItemClickListener != null) {
                        onItemClickListener.onItemClick((BaseViewHolder) vh, realPosition);
                    }
                    if (onItemViewClickListener != null) {
                        onItemViewClickListener.onItemClick((BaseViewHolder) vh, v, realPosition);
                    }
                }
            });
            vh.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    if (onItemLongClickListener != null) {
                        onItemLongClickListener.onItemLongClick((BaseViewHolder) vh, realPosition);
                    }
                    return true;
                }
            });
            onBindViewHolderHF((BaseViewHolder) vh, realPosition, mDataList.get(realPosition));
        }
    }

    protected void prepareHeaderFooter(HeaderFooterViewHolder vh, View view) {
        vh.base.removeAllViews();
        vh.base.addView(view);
    }

    protected abstract void onBindViewHolderHF(BaseViewHolder baseViewHolder, int realPosition, DATA data);

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

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

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

    public void notifyListDataChanged(List<DATA> dataList, boolean isRefresh) {
        if (isRefresh) {
            mDataList.clear();
        }
        if (dataList != null) {
            mDataList.addAll(dataList);
        }
        notifyDataSetChanged();
    }

    public void addHeaderView(View headerView) {
        if (!mHeaders.contains(headerView)) {
            mHeaders.add(headerView);
            notifyItemInserted(mHeaders.size() - 1);
        }
    }

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

    public void addHeaderView(View headerView, int position) {
        if (position > mHeaders.size()) return;
        if (!mHeaders.contains(headerView)) {
            mHeaders.add(headerView);
            notifyItemInserted(position);
        }
    }

    @Override
    public int getHeaderLayoutCount() {
        return mHeaders.size();
    }

    public void addFooter(View footer) {
        if (!mFooters.contains(footer)) {
            mFooters.add(footer);
            notifyItemInserted(mHeaders.size() + getItemCountHF() + mFooters.size() - 1);
        }
    }

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


    @Override
    public boolean isEmpty() {
        return mHeaders.size() == 0 && getItemCount() == 0;
    }


    public void addOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public void addOnItemViewClickListener(OnItemViewClickListener onItemViewClickListener) {
        this.onItemViewClickListener = onItemViewClickListener;
    }

    public interface OnItemClickListener {
        void onItemClick(BaseViewHolder vh, int position);
    }

    public interface OnItemViewClickListener {
        void onItemClick(BaseViewHolder vh, View view, int position);
    }


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

    public interface OnItemLongClickListener {
        void onItemLongClick(BaseViewHolder vh, int position);
    }

    public static class HeaderFooterViewHolder extends RecyclerView.ViewHolder {
        FrameLayout base;

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

    public static class BaseViewHolder<HOLDER extends ViewDataBinding> extends RecyclerView.ViewHolder {
        private HOLDER dataBinding;

        public BaseViewHolder(HOLDER dataBinding) {
            super(dataBinding.getRoot());
            this.dataBinding = dataBinding;
        }

        public HOLDER getDataBinding() {
            return dataBinding;
        }
    }
}