package com.yuyh.library.view.list.indexablelistview;

import android.app.Activity;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.support.v7.widget.AppCompatTextView;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.yuyh.library.R;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by YoKeyword on 16/3/21.
 */
public class IndexableStickyListView extends FrameLayout implements AdapterView.OnItemClickListener, AbsListView.OnScrollListener {
    private static final int MSG_BIND_DATA = 1;
    private OnItemTitleClickListener mOnTitleListener;
    private OnItemContentClickListener mOnContentListener;

    private int mBarTextColor, mBarSelectedTextColor, mRightOverlayColor;
    private float mBarTextSize;
    private int mTypeOverlay;

    private ArrayList<View> mAddHeaderViewList;

    private ListView mListView;
    private IndexBar mIndexBar;
    private SearchLayout mSearchLayout;
    private TextView mTvOverlay;
    private AppCompatTextView mTvRightOverlay;

    private Context mContext;
    private IndexableAdapter mAdapter;

    private List<IndexEntity> mItems;
    private IndexHeaderEntity[] mHeaderEntities;

    private int mCurrentScrollItemPosition, mCurrentScrollItemTop;
    private int mTitleHeight;
    private SparseArray<String> mTitleMap;
    private TextView mStickView;

    private HandlerThread mBindDataHandlerThread;
    private Handler mBindDataHandler;

    public IndexableStickyListView(Context context) {
        super(context);
        init(context, null);
    }

    public IndexableStickyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public IndexableStickyListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        mContext = context;

        if (attrs != null) {
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IndexableStickyListView);
            mBarTextColor = a.getColor(R.styleable.IndexableStickyListView_indexBar_textColor, getResources().getColor(R.color.default_indexBar_textcolor));
            mBarTextSize = a.getDimension(R.styleable.IndexableStickyListView_indexBar_textSize, getResources().getDimension(R.dimen.default_indexBar_textSize));
            mBarSelectedTextColor = a.getColor(R.styleable.IndexableStickyListView_indexBar_selected_textColor, getResources().getColor(R.color.dafault_indexBar_selected_textColor));
            mRightOverlayColor = a.getColor(R.styleable.IndexableStickyListView_indexListView_rightOverlayColor, getResources().getColor(R.color.default_indexListView_rightOverlayColor));
            mTypeOverlay = a.getInt(R.styleable.IndexableStickyListView_indexListView_type_overlay, 0);
            a.recycle();
        }


        if (mContext instanceof Activity) {
            ((Activity) mContext).getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
        }

        mListView = new ListView(context);
        mListView.setVerticalScrollBarEnabled(false);
        mListView.setOverScrollMode(View.OVER_SCROLL_NEVER);
        mListView.setDivider(null);
        addView(mListView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

        mIndexBar = new IndexBar(context, mBarTextColor, mBarSelectedTextColor, mBarTextSize);
        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        params.gravity = Gravity.RIGHT;
        params.topMargin = IndexBar.dp2px(context, 16);
        params.bottomMargin = params.topMargin;
        addView(mIndexBar, params);
        if (mTypeOverlay == 1) {
            showCenterOverlayView(true);
        } else if (mTypeOverlay == 2) {
            showRightOverlayView(true, mRightOverlayColor);
        }

        mSearchLayout = new SearchLayout(context);
        LayoutParams paramsLayout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        addView(mSearchLayout, paramsLayout);
        mSearchLayout.setVisibility(GONE);

        mListView.setOnItemClickListener(this);
        mListView.setOnScrollListener(this);

        mIndexBar.setOnIndexSelectedListener(new IndexBar.OnIndexTitleSelectedListener() {
            @Override
            public void onSelection(int position, String indexTitle) {
                if (mStickView != null) {
                    if (!mStickView.getText().toString().equals(indexTitle)) {
                        mStickView.setText(indexTitle);
                    }
                    if (mStickView.getY() != 0) {
                        mStickView.setY(0);
                    }
                }
            }
        });
    }

    public void addHeaderView(View view) {
        if (mListView == null) return;
        if (mAddHeaderViewList == null) {
            mAddHeaderViewList = new ArrayList<>();
        }
        mListView.addHeaderView(view);

        mAddHeaderViewList.add(view);
    }

    public void removeHeaderView(View view) {
        if (mListView == null || mAddHeaderViewList == null || !mAddHeaderViewList.contains(view)) {
            return;
        }
        mListView.removeHeaderView(view);

        mAddHeaderViewList.remove(view);
    }

    public int getHeaderViewsCount() {
        if (mListView == null) return 0;
        return mListView.getHeaderViewsCount();
    }

    public ArrayList<View> getHeaderViews() {
        return mAddHeaderViewList;
    }

    /**
     * @return IndexListView的ListView
     */
    public ListView getListView() {
        return mListView;
    }

    /**
     * @return IndexListView中心位置的 悬浮TextView
     */
    public TextView getCenterOverlayTextView() {
        return mTvOverlay;
    }

    public IndexBar getIndexBar() {
        return mIndexBar;
    }

    /**
     * @param show 是否显示IndexListView右侧位置的 悬浮TextView
     */
    public void showRightOverlayView(boolean show, int color) {
        if (show) {
            if (mTvRightOverlay == null) {
                initRightOverlayTextView(color);
                addView(mTvRightOverlay);
                mTvRightOverlay.invalidate();
                mIndexBar.showTouchOverlayView(mTvRightOverlay);
            }
        } else {
            if (mTvRightOverlay != null) {
                removeView(mTvRightOverlay);
                mIndexBar.showTouchOverlayView(null);
            }
        }
    }

    /**
     * @param show 是否显示IndexListView中心位置的 悬浮TextView
     */
    public void showCenterOverlayView(boolean show) {
        if (show) {
            if (mTvOverlay == null) {
                initOverlayTextView();
            }
            addView(mTvOverlay);
            mIndexBar.setOverlayView(mTvOverlay);
        } else {
            if (mTvOverlay != null) {
                removeView(mTvOverlay);
            }
            mIndexBar.setOverlayView(null);
        }
    }

    private void initOverlayTextView() {
        mTvOverlay = new TextView(mContext);
        mTvOverlay.setBackgroundResource(R.drawable.bg_translucent_4dp);
        mTvOverlay.setTextColor(Color.WHITE);
        mTvOverlay.setTextSize(40);
        mTvOverlay.setGravity(Gravity.CENTER);
        int size = IndexBar.dp2px(mContext, 70);
        LayoutParams params = new LayoutParams(size, size);
        params.gravity = Gravity.CENTER;
        mTvOverlay.setLayoutParams(params);
        mTvOverlay.setVisibility(INVISIBLE);
    }

    private void initRightOverlayTextView(int color) {
        mTvRightOverlay = new AppCompatTextView(mContext);
        mTvRightOverlay.setBackgroundResource(R.drawable.bg_right_overlay);
        mTvRightOverlay.setSupportBackgroundTintList(ColorStateList.valueOf(color));
        mTvRightOverlay.setTextColor(Color.WHITE);
        mTvRightOverlay.setTextSize(38);
        mTvRightOverlay.setGravity(Gravity.CENTER);
        int size = IndexBar.dp2px(mContext, 72);
        LayoutParams params = new LayoutParams(size, size);
        params.rightMargin = IndexBar.dp2px(mContext, 33);
        params.gravity = Gravity.RIGHT;
        mTvRightOverlay.setLayoutParams(params);
        mTvRightOverlay.setVisibility(INVISIBLE);
    }

    private static class BindDatasHanlder extends Handler {
        private final WeakReference<IndexableStickyListView> mIndexListView;

        public BindDatasHanlder(Looper looper, IndexableStickyListView indexListView) {
            super(looper);
            mIndexListView = new WeakReference<>(indexListView);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            final IndexableStickyListView indexListView = mIndexListView.get();

            indexListView.mAdapter.setNeedShutdown(false);
            indexListView.mAdapter.setDatas(indexListView.mItems, indexListView.mHeaderEntities);
            if (indexListView.mAdapter.isNeedShutdown()) return;
            ((Activity) indexListView.mContext).runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    indexListView.updateListView();
                }
            });
        }
    }

    /**
     * 绑定数据
     *
     * @param items          继承IndexEntity的List
     * @param headerEntities IndexListView自定义Header 如添加定位,热门城市等
     * @param <T>            继承IndexEntity
     */
    public <T extends IndexEntity> void bindDatas(final List<T> items, final IndexHeaderEntity... headerEntities) {
        mItems = new ArrayList<>();
        mHeaderEntities = new IndexHeaderEntity[headerEntities.length];

        mItems.addAll(items);
        for (int i = 0; i < headerEntities.length; i++) {
            mHeaderEntities[i] = headerEntities[i];
        }

        if (mAdapter == null) {
            return;
        }

        if (mContext instanceof Activity) {
            mAdapter.setNeedShutdown(true);

            if (mBindDataHandlerThread == null) {
                mBindDataHandlerThread = new HandlerThread("BindData_Thread");
                mBindDataHandlerThread.start();
                mBindDataHandler = new BindDatasHanlder(mBindDataHandlerThread.getLooper(), this);
            }
            mBindDataHandler.sendEmptyMessage(MSG_BIND_DATA);
        } else {
            mAdapter.setDatas(mItems, headerEntities);
            updateListView();
        }
    }


    /**
     * 搜索过滤处理
     *
     * @param newText 变化后的内容
     */
    public void searchTextChange(final String newText) {
        mIndexBar.searchTextChange(newText);
    }

    /**
     * 为IndexListView设置Adapter
     */
    public <T extends IndexEntity> void setAdapter(IndexableAdapter<T> adapter) {
        mAdapter = adapter;
        mAdapter.setParent(this);
        mListView.setAdapter(adapter);

        if (mItems != null) {
            bindDatas(mItems, mHeaderEntities);
        }
    }

    /**
     * 设置 IndexListView 标题头 部分的点击事件
     *
     * @param listener
     */
    public void setOnItemTitleClickListener(OnItemTitleClickListener listener) {
        mOnTitleListener = listener;
    }

    /**
     * 设置 IndexListView 内容item 部分的点击事件
     *
     * @param listener
     */
    public void setOnItemContentClickListener(OnItemContentClickListener listener) {
        mOnContentListener = listener;
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (position < mListView.getHeaderViewsCount()) return;
        Object object = mAdapter.getItem(position - mListView.getHeaderViewsCount());
        if (mOnTitleListener != null && object instanceof String) {
            String title = (String) object;
            mOnTitleListener.onItemClick(view, title);
        } else if (mOnContentListener != null && object instanceof IndexEntity) {
            IndexEntity indexEntity = (IndexEntity) object;
            mOnContentListener.onItemClick(view, indexEntity);
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        mIndexBar.onListViewScrollStateChanged(scrollState);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        mIndexBar.onListViewScroll(firstVisibleItem);

        if (mTitleHeight == 0 || mTitleMap == null) return;

        if (firstVisibleItem < mListView.getHeaderViewsCount()) {
            if (mStickView.getVisibility() == VISIBLE) {
                mStickView.setVisibility(INVISIBLE);
            }
            return;
        } else if (firstVisibleItem == mListView.getHeaderViewsCount()) {
            if (mStickView.getVisibility() != VISIBLE) {
                if (mAdapter == null || !mAdapter.isFilter()) {
                    mStickView.setVisibility(VISIBLE);
                }
            }
        }

        if (firstVisibleItem > mCurrentScrollItemPosition) {    // 向下
            mCurrentScrollItemPosition = firstVisibleItem;
            processStick(firstVisibleItem, totalItemCount);
        } else if (firstVisibleItem < mCurrentScrollItemPosition) { // 向上
            mCurrentScrollItemPosition = firstVisibleItem;
            processStick(firstVisibleItem, totalItemCount);
        } else {
            View firstView = mListView.getChildAt(0);
            if (firstView == null) return;

            int top = firstView.getTop();
            if (top < mCurrentScrollItemTop) {    // 向下
                mCurrentScrollItemTop = top;
                processStick(firstVisibleItem, totalItemCount);
            } else {  // 向上
                mCurrentScrollItemTop = top;
                processStick(firstVisibleItem, totalItemCount);
            }
        }
    }

    private void processStick(int firstVisibleItem, int totalItemCount) {
        if (firstVisibleItem < totalItemCount - 1 && mTitleMap.get(firstVisibleItem - mListView.getHeaderViewsCount() + 1) != null) {
            int nextTop = mListView.getChildAt(1).getTop();

            if (nextTop <= mTitleHeight) {
                if (mStickView.getVisibility() != VISIBLE) {
                    if (mAdapter == null || !mAdapter.isFilter()) {
                        mStickView.setVisibility(VISIBLE);
                    }
                }
                mStickView.setTranslationY(nextTop - mTitleHeight);
            }
        }
    }

    public interface OnItemContentClickListener {
        void onItemClick(View v, IndexEntity indexEntity);
    }

    public interface OnItemTitleClickListener {
        void onItemClick(View v, String title);
    }

    /**
     * 更新相关View数据
     */
    private void updateListView() {
        mListView.post(new Runnable() {
            @Override
            public void run() {
                final TextView titleTextView = mAdapter.getTitleTextView();
                titleTextView.post(new Runnable() {
                    @Override
                    public void run() {
                        mTitleHeight = titleTextView.getHeight();
                    }
                });
            }
        });

        mTitleMap = mAdapter.getTitleMap();
        if (mStickView == null) {
            if (mTitleMap.size() > 0) {
                View view = mAdapter.getView(mTitleMap.keyAt(0), null, mListView);
                mStickView = (TextView) view;
                addView(mStickView, 1);

                mStickView.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (mOnTitleListener != null) {
                            mOnTitleListener.onItemClick(v, mStickView.getText().toString());
                        }
                    }
                });

                if (mListView.getHeaderViewsCount() > 0) {
                    mStickView.setVisibility(INVISIBLE);
                }
            }

            mIndexBar.setOnSearchResultListener(new IndexBar.OnSearchResultListener() {
                @Override
                public void onStart() {
                    if (!mSearchLayout.isProgressVisible()) {
                        if (mContext instanceof Activity) {
                            ((Activity) mContext).runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    mSearchLayout.showProgress();
                                }
                            });
                        }
                    }
                }

                @Override
                public void onResult(boolean isSearch, int dataSize) {
                    if (mAdapter == null) return;

                    if (!isSearch || dataSize > 0) {
                        mSearchLayout.hide();
                    } else {
                        mSearchLayout.showTip();
                    }

                    mListView.setSelection(1);
                    if (mAdapter.isFilter()) {
                        if (mAddHeaderViewList != null) {
                            for (View view : mAddHeaderViewList) {
                                if (view.getHeight() != 0) {
                                    view.setTag(view.getHeight());
                                    view.getLayoutParams().height = 1;
                                }
                            }
                        }
                        if (mStickView != null && mStickView.getVisibility() == VISIBLE) {
                            mStickView.setVisibility(INVISIBLE);
                        }
                    } else {
                        if (mAddHeaderViewList != null) {
                            for (View view : mAddHeaderViewList) {
                                view.getLayoutParams().height = (int) view.getTag();
                            }
                        }
                        if (mStickView != null && mStickView.getVisibility() != VISIBLE) {
                            mStickView.setVisibility(VISIBLE);
                        }
                    }
                    mListView.smoothScrollToPosition(0);
                }
            });
        } else {
            if (mTitleMap.size() == 0) {
                removeView(mStickView);
                mStickView = null;
            } else {
                String title = mAdapter.getItemTitle(mListView.getFirstVisiblePosition());
                mStickView.setText(title);
            }
        }

        mAdapter.notifyDataSetChanged();
        mIndexBar.setListView(mListView);
        mIndexBar.postInvalidate();
    }

    @Override
    protected void onDetachedFromWindow() {
        if (mBindDataHandlerThread != null) {
            mBindDataHandlerThread.quit();
        }
        super.onDetachedFromWindow();
    }
}