package com.gh.gamecenter.common.view;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

import com.gh.gamecenter.core.utils.DisplayUtils;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshKernel;
import com.scwang.smartrefresh.layout.constant.RefreshState;
import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener;

public class HomeSmartRefreshLayout extends SmartRefreshLayout {
    private final int mFloorHeight = DisplayUtils.getScreenWidth() - DisplayUtils.dip2px(48F) - DisplayUtils.getStatusBarHeight(getContext().getResources());

    public HomeSmartRefreshLayout(Context context) {
        super(context);
        mKernel = new HomeRefreshKernelImpl();
    }

    public HomeSmartRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        mKernel = new HomeRefreshKernelImpl();
    }

    public void setFloorDuration(int duration) {
        this.mFloorDuration = duration;
    }

    @Override
    protected void overSpinner() {
        if (mState == RefreshState.TwoLevel) {
            if (mCurrentVelocity > -1000 && mSpinner > mFloorHeight / 2) {
                ValueAnimator animator = mKernel.animSpinner(mFloorHeight);
                if (animator != null) {
                    animator.setDuration(mFloorDuration);
                }
            } else if (mIsBeingDragged) {
                mKernel.finishTwoLevel();
            }
        } else if (mState == RefreshState.Loading
                || (mEnableFooterFollowWhenNoMoreData && mFooterNoMoreData && mFooterNoMoreDataEffective && mSpinner < 0 && isEnableRefreshOrLoadMore(mEnableLoadMore))) {
            if (mSpinner < -mFooterHeight) {
                mKernel.animSpinner(-mFooterHeight);
            } else if (mSpinner > 0) {
                mKernel.animSpinner(0);
            }
        } else if (mState == RefreshState.Refreshing) {
            if (mSpinner > mHeaderHeight) {
                mKernel.animSpinner(mHeaderHeight);
            } else if (mSpinner < 0) {
                mKernel.animSpinner(0);
            }
        } else if (mState == RefreshState.PullDownToRefresh) {
            mKernel.setState(RefreshState.PullDownCanceled);
        } else if (mState == RefreshState.PullUpToLoad) {
            mKernel.setState(RefreshState.PullUpCanceled);
        } else if (mState == RefreshState.ReleaseToRefresh) {
            mKernel.setState(RefreshState.Refreshing);
        } else if (mState == RefreshState.ReleaseToLoad) {
            mKernel.setState(RefreshState.Loading);
        } else if (mState == RefreshState.ReleaseToTwoLevel) {
            mKernel.setState(RefreshState.TwoLevelReleased);
        } else if (mState == RefreshState.RefreshReleased) {
            if (reboundAnimator == null) {
                mKernel.animSpinner(mHeaderHeight);
            }
        } else if (mState == RefreshState.LoadReleased) {
            if (reboundAnimator == null) {
                mKernel.animSpinner(-mFooterHeight);
            }
        } else if (mState == RefreshState.LoadFinish) {
            /*
             * 2020-5-26 修复 finishLoadMore 中途
             * 拖拽导致 状态重置 最终导致 显示 NoMoreData Footer 菊花却任然在转的情况
             * overSpinner 时 LoadFinish 状态无任何操作即可
             */
        } else if (mSpinner != 0) {
            mKernel.animSpinner(0);
        }
    }

    @Override
    protected void moveSpinnerInfinitely(float spinner) {
        final View thisView = this;
        if (mNestedInProgress && !mEnableLoadMoreWhenContentNotFull && spinner < 0) {
            if (!mRefreshContent.canLoadMore()) {
                /*
                 * 2019-1-22 修复 嵌套滚动模式下 mEnableLoadMoreWhenContentNotFull=false 无效的bug
                 */
                spinner = 0;
            }
        }
        if (mState == RefreshState.TwoLevel && spinner > 0 && mRefreshContent != null) {
            mKernel.moveSpinner(Math.min((int) spinner, mFloorHeight), true);
        } else if (mState == RefreshState.Refreshing && spinner >= 0) {
            if (spinner < mHeaderHeight) {
                mKernel.moveSpinner((int) spinner, true);
            } else {
                final float M = (mHeaderMaxDragRate - 1) * mHeaderHeight;
                final float H = Math.max(mScreenHeightPixels * 4 / 3, thisView.getHeight()) - mHeaderHeight;
                final float x = Math.max(0, (spinner - mHeaderHeight) * mDragRate);
                final float y = Math.min(M * (1 - (float) Math.pow(100, -x / (H == 0 ? 1 : H))), x);// 公式 y = M(1-100^(-x/H))
                mKernel.moveSpinner((int) y + mHeaderHeight, true);
            }
        } else if (spinner < 0 && (mState == RefreshState.Loading
                || (mEnableFooterFollowWhenNoMoreData && mFooterNoMoreData && mFooterNoMoreDataEffective && isEnableRefreshOrLoadMore(mEnableLoadMore))
                || (mEnableAutoLoadMore && !mFooterNoMoreData && isEnableRefreshOrLoadMore(mEnableLoadMore)))) {
            if (spinner > -mFooterHeight) {
                mKernel.moveSpinner((int) spinner, true);
            } else {
                final float M = (mFooterMaxDragRate - 1) * mFooterHeight;
                final float H = Math.max(mScreenHeightPixels * 4 / 3, thisView.getHeight()) - mFooterHeight;
                final float x = -Math.min(0, (spinner + mFooterHeight) * mDragRate);
                final float y = -Math.min(M * (1 - (float) Math.pow(100, -x / (H == 0 ? 1 : H))), x);// 公式 y = M(1-100^(-x/H))
                mKernel.moveSpinner((int) y - mFooterHeight, true);
            }
        } else if (spinner >= 0) {
            final float M = mHeaderMaxDragRate * mHeaderHeight;
            final float H = Math.max(mScreenHeightPixels / 2, thisView.getHeight());
            final float x = Math.max(0, spinner * mDragRate);
            final float y = Math.min(M * (1 - (float) Math.pow(100, -x / (H == 0 ? 1 : H))), x);// 公式 y = M(1-100^(-x/H))
            mKernel.moveSpinner((int) y, true);
        } else {
            final float M = mFooterMaxDragRate * mFooterHeight;
            final float H = Math.max(mScreenHeightPixels / 2, thisView.getHeight());
            final float x = -Math.min(0, spinner * mDragRate);
            final float y = -Math.min(M * (1 - (float) Math.pow(100, -x / (H == 0 ? 1 : H))), x);// 公式 y = M(1-100^(-x/H))
            mKernel.moveSpinner((int) y, true);
        }
        if (mEnableAutoLoadMore && !mFooterNoMoreData && isEnableRefreshOrLoadMore(mEnableLoadMore) && spinner < 0
                && mState != RefreshState.Refreshing
                && mState != RefreshState.Loading
                && mState != RefreshState.LoadFinish) {
            if (mDisableContentWhenLoading) {
                animationRunnable = null;
                mKernel.animSpinner(-mFooterHeight);
            }
            setStateDirectLoading(false);
            /*
             * 自动加载模式时，延迟触发 onLoadMore ，mReboundDuration 保证动画能顺利执行
             */
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (mLoadMoreListener != null) {
                        mLoadMoreListener.onLoadMore(HomeSmartRefreshLayout.this);
                    } else if (mOnMultiPurposeListener == null) {
                        finishLoadMore(2000);//如果没有任何加载监听器，两秒之后自动关闭
                    }
                    final OnLoadMoreListener listener = mOnMultiPurposeListener;
                    if (listener != null) {
                        listener.onLoadMore(HomeSmartRefreshLayout.this);
                    }
                }
            }, mReboundDuration);
        }
    }

    public class HomeRefreshKernelImpl extends RefreshKernelImpl {
        @Override
        public RefreshKernel startTwoLevel(boolean open) {
            if (open) {
                AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (animation != null && animation.getDuration() == 0) {
                            return;//0 表示被取消
                        }
                        mKernel.setState(RefreshState.TwoLevel);
                    }
                };
                ValueAnimator animator = animSpinner(mFloorHeight);
                if (animator != null && animator == reboundAnimator) {
                    animator.setDuration(mFloorDuration);
                    animator.addListener(listener);
                } else {
                    listener.onAnimationEnd(null);
                }
            } else {
                if (animSpinner(0) == null) {
                    notifyStateChanged(RefreshState.None);
                }
            }
            return this;
        }
    }
}
