package com.gh.gamecenter.common.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
import androidx.viewpager.widget.ViewPager;

import com.gh.gamecenter.common.R;
import com.gh.gamecenter.core.utils.DisplayUtils;
import com.google.android.material.tabs.TabLayout;

/**
 * Created by khy on 2/12/17.
 */

public class TabIndicatorView extends View implements ViewPager.OnPageChangeListener {

    private TabLayout mTabLayout;

    private int mIndicatorSpace;

    private int mIndicatorHeight;

    private int mIndicatorWidth;

    private int mIndicatorColor = 0;

    private float mLastPositionRatio = 1F;

    private boolean mDisableIndicatorScaling = false;

    private GradientDrawable mGradientDrawable;
    private Drawable mCustomDrawable;

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

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

    public TabIndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mIndicatorWidth = (int) context.getResources().getDimension(R.dimen.default_tab_indicator_width);

        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabIndicatorView);
        if (a.hasValue(R.styleable.TabIndicatorView_indicatorColor)) {
            mIndicatorColor = a.getColor(R.styleable.TabIndicatorView_indicatorColor, ContextCompat.getColor(context, R.color.text_theme));
            mGradientDrawable = new GradientDrawable();
            mGradientDrawable.setShape(GradientDrawable.RECTANGLE);
            mGradientDrawable.setColor(mIndicatorColor);
            mGradientDrawable.setCornerRadius(Integer.MAX_VALUE);
        }
        if (a.hasValue(R.styleable.TabIndicatorView_indicatorDrawable)) {
            mCustomDrawable = a.getDrawable(R.styleable.TabIndicatorView_indicatorDrawable);
        }
        if (a.hasValue(R.styleable.TabIndicatorView_disableIndicatorScaling)) {
            mDisableIndicatorScaling = a.getBoolean(R.styleable.TabIndicatorView_disableIndicatorScaling, false);
        }
        a.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mIndicatorHeight = MeasureSpec.getSize(heightMeasureSpec);
    }

    public void updateIndicatorDrawable(Drawable drawable) {
        mCustomDrawable = drawable;
        invalidate();
    }

    public void updateIndicatorColor(int color) {
        mIndicatorColor = ContextCompat.getColor(getContext(), color);
        mGradientDrawable = new GradientDrawable();
        mGradientDrawable.setShape(GradientDrawable.RECTANGLE);
        mGradientDrawable.setColor(mIndicatorColor);
        mGradientDrawable.setCornerRadius(Integer.MAX_VALUE);
        invalidate();
    }

    public void setupWithTabLayout(final TabLayout tableLayout) {
        mTabLayout = tableLayout;

        tableLayout.setSelectedTabIndicatorColor(Color.TRANSPARENT);
        tableLayout.getViewTreeObserver().addOnScrollChangedListener(() -> {
            if (mTabLayout.getScrollX() != getScrollX())
                scrollTo(mTabLayout.getScrollX(), mTabLayout.getScrollY());
        });

        ViewCompat.setElevation(this, ViewCompat.getElevation(mTabLayout));

        //清除Tab background
        for (int tab = 0; tab < tableLayout.getTabCount(); tab++) {
            View tabView = getTabViewByPosition(tab);
            if (tabView != null) tabView.setBackgroundResource(0);
        }
    }

    public void setupWithViewPager(ViewPager viewPager) {
        viewPager.addOnPageChangeListener(this);
    }

    public void setIndicatorWidth(int width) {
        if (width > 0) this.mIndicatorWidth = DisplayUtils.dip2px(getContext(), width);
    }

    public void setIndicatorSpace(int space) {
        this.mIndicatorSpace = DisplayUtils.dip2px(getContext(), space);
    }

    public void setIndicatorLastPositionRatio(float lastPositionRatio) {
        this.mLastPositionRatio = lastPositionRatio;
    }

    private int getIndicatorSpace(int position) {
        if (mIndicatorSpace != 0) return mIndicatorSpace;
        if (mIndicatorWidth != 0) {
            View tag = getTabViewByPosition(position);
            if (tag != null) return (tag.getWidth() - mIndicatorWidth) / 2;
        }
        return 0;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Drawable drawable;
        if (mCustomDrawable != null) {
            drawable = mCustomDrawable;
        } else if (mGradientDrawable != null) {
            drawable = mGradientDrawable;
        } else {
            drawable = getResources().getDrawable(R.drawable.ask_tab_indicator_bg); // 固定Indicator背景 有需要可以自行更改
        }

        // 是否需要禁用指示器拉伸
        if (mDisableIndicatorScaling) {
            int currentWidth = r - l;
            int newLeft = l;
            int newRight = r;

            if (currentWidth != mIndicatorWidth) {
                int widthOffset = currentWidth - mIndicatorWidth;
                newLeft = l + (widthOffset / 2);
                newRight = newLeft + mIndicatorWidth;
            }
            drawable.setBounds(newLeft, t, newRight, b);
        } else {
            drawable.setBounds(l, t, r, b);
        }

        drawable.draw(canvas);
    }

    int l;
    int t;
    int r;
    int b;

    public void generatePath(int position, float positionOffset) {
        RectF range = new RectF();
        View tabView = getTabViewByPosition(position);

        if (tabView == null) return;

        int left, top, right, bottom;
        left = top = right = bottom = 0;

        if (positionOffset > 0.f && position < mTabLayout.getTabCount() - 1) {
            View nextTabView = getTabViewByPosition(position + 1);
            if (nextTabView != null) {
                float positionRatio;
                if (position == mTabLayout.getTabCount() - 2) {
                    positionRatio = mLastPositionRatio;
                } else {
                    positionRatio = 1F;
                }
                left += (int) getTabLayoutLeftOffset() + (nextTabView.getLeft() * (positionOffset / positionRatio) + tabView.getLeft() * (1.f - (positionOffset / positionRatio)));
                right += (int) getTabLayoutLeftOffset() + (nextTabView.getRight() * (positionOffset / positionRatio) + tabView.getRight() * (1.f - (positionOffset / positionRatio)));
            }
            left += getIndicatorSpace(position);
            right -= getIndicatorSpace(position);
            top = tabView.getTop() + getPaddingTop();
            bottom = tabView.getBottom() - getPaddingBottom();
            range.set(left, top, right, bottom);
        } else {
            left = getTabLayoutLeftOffset() + tabView.getLeft() + getIndicatorSpace(position);
            right = getTabLayoutLeftOffset() + tabView.getRight() - getIndicatorSpace(position);
            top = tabView.getTop() + getPaddingTop();
            bottom = tabView.getBottom() - getPaddingBottom();
            range.set(left, top, right, bottom);

            if (range.isEmpty()) return;
        }
        r = right;
        l = left;
        t = top;
        b = top + mIndicatorHeight;

        invalidate();
    }

    private int getTabLayoutLeftOffset() {
        if (mTabLayout == null) return 0;
        int offset = mTabLayout.getPaddingLeft();
        if (mTabLayout.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
            offset += ((ViewGroup.MarginLayoutParams) mTabLayout.getLayoutParams()).leftMargin;
        }
        return offset;
    }

    private View getTabViewByPosition(int position) {
        if (mTabLayout != null && mTabLayout.getTabCount() > 0) {
            ViewGroup tabStrip = (ViewGroup) mTabLayout.getChildAt(0);
            return tabStrip != null ? tabStrip.getChildAt(position) : null;
        }

        return null;
    }


    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        generatePath(position, positionOffset);
    }

    @Override
    public void onPageSelected(int position) {
        if (mTabLayout.getSelectedTabPosition() != position) {
            TabLayout.Tab tab = mTabLayout.getTabAt(position);
            if (tab != null) tab.select();
        }

    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}