package com.lzx.demo.view;

import android.content.Context;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.widget.LinearLayout;
import android.widget.ScrollView;

import com.github.jdsjlzx.interfaces.IRefreshHeader;
import com.github.jdsjlzx.recyclerview.AppBarStateChangeListener;
import com.github.jdsjlzx.view.ArrowRefreshHeader;
import com.lzx.demo.R;


/**
 * 自定义下拉刷新ScrollView
 * <p/>
 */
public class PullScrollView extends ScrollView {
    private RefreshListener mRefreshListener;
    private OnScrollChangeListener scrollViewListener = null;

    private IRefreshHeader mRefreshHeader;
    private boolean isRefreshEnabled = true;    //设置下拉刷新是否可用
    private float   dragRate         = 2;       //下拉刷新滑动阻力系数,越大需要手指下拉的距离越大才能刷新

    private boolean isRefreshing;   //是否正在刷新
    private float mLastY = -1;      //上次触摸的的Y值
    private int     topY;
    private float   sumOffSet;
    private boolean isAdded;

    private AppBarStateChangeListener.State appbarState = AppBarStateChangeListener.State.EXPANDED;

    public PullScrollView(Context context) {
        this(context, null);
    }

    public PullScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PullScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        if (isRefreshEnabled) {
            mRefreshHeader = new ArrowRefreshHeader(getContext());
        }

        getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (!isAdded) {
                    isAdded = true;

                    //解决和AppBarLayout冲突的问题
                    ViewParent p = getParent();
                    while (p != null) {
                        if (p instanceof CoordinatorLayout) {
                            break;
                        }
                        p = p.getParent();
                    }

                    if (p != null) {
                        AppBarLayout appBarLayout = null;
                        CoordinatorLayout coordinatorLayout = (CoordinatorLayout) p;
                        final int childCount = coordinatorLayout.getChildCount();
                        for (int i = childCount - 1; i >= 0; i--) {
                            final View child = coordinatorLayout.getChildAt(i);
                            if (child instanceof AppBarLayout) {
                                appBarLayout = (AppBarLayout) child;
                                break;
                            }
                        }

                        if (appBarLayout != null) {
                            appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() {
                                @Override
                                public void onStateChanged(AppBarLayout appBarLayout, State state) {
                                    appbarState = state;
                                }
                            });
                        }
                    }

                    setLayout();
                }


            }
        });
    }

    private void setLayout() {
        ViewGroup group = (ViewGroup) getParent();
        LinearLayout container = new LinearLayout(getContext());
        container.setOrientation(LinearLayout.VERTICAL);
        int index = group.indexOfChild(this);
        group.removeView(this);
        group.addView(container, index, getLayoutParams());

        container.addView(mRefreshHeader.getHeaderView(), new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        container.addView(this, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    }

    public View getRefreshHeaderView() {
        return mRefreshHeader.getHeaderView();
    }

    /**
     * 设置下拉刷新上拉加载回调
     */
    public void setRefreshListener(RefreshListener listener) {
        mRefreshListener = listener;
    }

    /**
     * 设置自定义的header
     */
    public void setRefreshHeader(IRefreshHeader mRefreshHeader) {
        this.mRefreshHeader = mRefreshHeader;
    }

    /**
     * 下拉刷新是否可用
     */
    public void setPullRefreshEnabled(boolean enabled) {
        isRefreshEnabled = enabled;
    }

    /**
     * 下拉刷新滑动阻力系数,越大需要手指下拉的距离越大才能刷新
     */
    public void setDragRate(int dragRate) {
        this.dragRate = dragRate;
    }

    /**
     * 设置下拉刷新的进度条风格
     */
    public void setRefreshProgressStyle(int style) {
        if (mRefreshHeader != null && mRefreshHeader instanceof ArrowRefreshHeader) {
            ((ArrowRefreshHeader) mRefreshHeader).setProgressStyle(style);
        }
    }

    /**
     * 设置下拉刷新的箭头图标
     */
    public void setArrowImageView(int resId) {
        if (mRefreshHeader != null && mRefreshHeader instanceof ArrowRefreshHeader) {
            ((ArrowRefreshHeader) mRefreshHeader).setArrowImageView(resId);
        }
    }

    /**
     * 设置颜色
     * @param indicatorColor Only call the method setRefreshProgressStyle(int style) to take effect
     * @param hintColor
     * @param backgroundColor
     */
    public void setHeaderViewColor(int indicatorColor, int hintColor, int backgroundColor) {
        if (mRefreshHeader != null && mRefreshHeader instanceof ArrowRefreshHeader) {
            ArrowRefreshHeader arrowRefreshHeader = ((ArrowRefreshHeader) mRefreshHeader);
            arrowRefreshHeader.setIndicatorColor(ContextCompat.getColor(getContext(),indicatorColor));
            arrowRefreshHeader.setHintTextColor(hintColor);
            arrowRefreshHeader.setViewBackgroundColor(backgroundColor);
        }

    }


    /**
     * 手动调用直接刷新,无下拉效果
     */
    public void refresh() {
        if (mRefreshListener != null) {
            isRefreshing = true;
            mRefreshListener.onRefresh();
        }
    }

    /**
     * 手动调用下拉刷新,有下拉效果
     */
    public void refreshWithPull() {
        setRefreshing(true);
        refresh();
    }

    /**
     * 下拉刷新和到底加载完成
     */
    public void setRefreshCompleted() {
        if (isRefreshing) {
            isRefreshing = false;
            mRefreshHeader.refreshComplete();
        }
    }

    /**
     * 手动调用加载状态,此函数不会调用 {@link RefreshListener#onRefresh()}加载数据
     * 如果需要加载数据和状态显示调用 {@link #refreshWithPull()}
     */
    public void setRefreshing(final boolean refreshing) {
        if (refreshing && isRefreshEnabled) {
            isRefreshing = true;
            mRefreshHeader.onRefreshing();

            int offSet = mRefreshHeader.getHeaderView()
                                      .getMeasuredHeight();
            mRefreshHeader.onMove(offSet, offSet);
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (mLastY == -1) {
            mLastY = ev.getRawY();
        }

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastY = ev.getRawY();
                sumOffSet = 0;
                break;
            case MotionEvent.ACTION_MOVE:
                final float deltaY = (ev.getRawY() - mLastY) / dragRate;
                mLastY = ev.getRawY();
                sumOffSet += deltaY;
                if (isOnTop() && isRefreshEnabled && appbarState == AppBarStateChangeListener.State.EXPANDED) {
                    mRefreshHeader.onMove(deltaY, sumOffSet);
                    if (mRefreshHeader.getVisibleHeight() > 0 && !isRefreshing) {
                        return false;
                    }
                }
                break;
            default:
                mLastY = -1; // reset
                if (isOnTop() && isRefreshEnabled && appbarState == AppBarStateChangeListener.State.EXPANDED) {
                    if (mRefreshHeader.onRelease()) {
                        if (mRefreshListener != null) {
                            isRefreshing = true;
                            mRefreshListener.onRefresh();
                        }
                    }
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        topY = t;
        if (scrollViewListener != null) {
            scrollViewListener.onScrollChange(this, l, t, oldl, oldt);
        }
    }

    /**
     * 如果在HeaderView已经被添加到布局中,说明已经到顶部
     */
    private boolean isOnTop() {
        return topY == 0;
    }

    public void setScrollViewListener(OnScrollChangeListener scrollViewListener) {
        this.scrollViewListener = scrollViewListener;
    }


    public interface RefreshListener {
        void onRefresh();
    }

    public interface OnScrollChangeListener {
        /**
         * Called when the scroll position of a view changes.
         *
         * @param v The view whose scroll position has changed.
         * @param scrollX Current horizontal scroll origin.
         * @param scrollY Current vertical scroll origin.
         * @param oldScrollX Previous horizontal scroll origin.
         * @param oldScrollY Previous vertical scroll origin.
         */
        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
    }
}