package com.duben.microtribe.ui.widgets;

import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;

import com.duben.microtribe.utils.BubbleUtils;

@SuppressLint("DrawAllocation")
public class CycleProgress extends View {
    private static final long DURATION = 300;
    private int mViewWidth;
    private int mViewHeight;

    private final int mStrokeWidth;

    private int mProgressWidth;

    private final Paint mBgPaint;
    private final Paint mProgressPaint;

    private ValueAnimator mAnimator;

    // 动画数值(用于控制动画状态,因为同一时间内只允许有一种状态出现,具体数值处理取决于当前状态)
    private float mAnimatorValue;

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

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

    private final int mHeight;

    public CycleProgress(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mHeight = BubbleUtils.dp2px(15);
        mStrokeWidth = BubbleUtils.dp2px(1);
        mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBgPaint.setStyle(Paint.Style.FILL);
        mBgPaint.setStrokeWidth(mHeight);
        mBgPaint.setColor(Color.parseColor("#EFEFEF"));

        Paint mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mStrokePaint.setStyle(Paint.Style.STROKE);
        mStrokePaint.setStrokeWidth(mStrokeWidth);
        int mStrokeColor = Color.parseColor("#FB918A");
        mStrokePaint.setColor(mStrokeColor);

        mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mProgressPaint.setStrokeWidth(mHeight);
        mProgressPaint.setStyle(Paint.Style.FILL);

        Paint mMackTickPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mMackTickPaint.setStyle(Paint.Style.STROKE);
        mMackTickPaint.setStrokeWidth(mStrokeWidth);
        mMackTickPaint.setColor(mStrokeColor);

        setLayerType(LAYER_TYPE_HARDWARE, null);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mViewHeight = h;
        mViewWidth = w;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(widthMeasureSpec, mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        RectF rectF2 = new RectF(mStrokeWidth, mStrokeWidth, mViewWidth - mStrokeWidth, mHeight - mStrokeWidth);

        canvas.drawRoundRect(rectF2, mHeight / 2, mHeight / 2, mBgPaint);

        RectF rectF1 = new RectF(mStrokeWidth / 2, mStrokeWidth / 2, mProgressWidth - mStrokeWidth / 2, mViewHeight - mStrokeWidth / 2);
        Path path = new Path();

        Path dstPath = new Path();
        PathMeasure pathMeasure = new PathMeasure();
        path.moveTo(0, 0);
        path.lineTo(mViewWidth, 0);
        pathMeasure.setPath(path, false);
        pathMeasure.getSegment(0, pathMeasure.getLength() * mAnimatorValue, dstPath, true);
        //渐变
        Shader mShader = new LinearGradient(mStrokeWidth / 2, mStrokeWidth / 2, mProgressWidth, mHeight - mStrokeWidth / 2,
                Color.parseColor("#F96856"), Color.parseColor("#EC325C"), Shader.TileMode.REPEAT);
        //遮罩
        mProgressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        mProgressPaint.setShader(mShader);
        canvas.drawRoundRect(rectF1, mHeight / 2, mHeight / 2, mProgressPaint);
        mProgressPaint.setXfermode(null);
    }

    public void setCompleteNoAnim() {
        if (mAnimator != null) {
            mAnimator.cancel();
            mAnimator = null;
        }

        mProgressWidth = mViewWidth;
        invalidate();
    }

    public void setComplete() {
        if (mAnimator != null) {
            mAnimator.cancel();
            mAnimator = null;
        }

        int progress = 1;

        mProgressWidth = progress * mViewWidth;
        mAnimator = ValueAnimator.ofFloat(0, progress).setDuration(200);

        ValueAnimator.AnimatorUpdateListener mUpdateListener = animation -> {
            mAnimatorValue = (float) animation.getAnimatedValue();
            mProgressWidth = (int) (mAnimatorValue * mViewWidth);
            invalidate();
        };
        mAnimator.addUpdateListener(mUpdateListener);
        mAnimator.start();
    }

    /**
     * 0--1
     */
    public void startAnim() {
        int progress = 1;

        int delta = (int) (progress / 0.1);
        delta = delta == 0 ? 1 : delta;

        mProgressWidth = progress * mViewWidth;
        mAnimator = ValueAnimator.ofFloat(0.1f, progress).setDuration(delta * DURATION);
        mAnimator.setRepeatCount(ValueAnimator.INFINITE);

        ValueAnimator.AnimatorUpdateListener mUpdateListener = animation -> {
            mAnimatorValue = (float) animation.getAnimatedValue();
            mProgressWidth = (int) (mAnimatorValue * mViewWidth);
            invalidate();
        };
        mAnimator.addUpdateListener(mUpdateListener);
        mAnimator.start();
    }

    /**
     * 0--1
     */
    public void startOneAnim() {
        int progress = 1;

        int delta = (int) (progress / 0.1);
        delta = delta == 0 ? 1 : delta;

        mProgressWidth = progress * mViewWidth;
        mAnimator = ValueAnimator.ofFloat(0.1f, progress).setDuration(delta * DURATION);

        ValueAnimator.AnimatorUpdateListener mUpdateListener = animation -> {
            mAnimatorValue = (float) animation.getAnimatedValue();
            mProgressWidth = (int) (mAnimatorValue * mViewWidth);
            invalidate();
        };
        mAnimator.addUpdateListener(mUpdateListener);
        mAnimator.start();
    }

    public void resumeAnim() {
        if (mAnimator != null) {
            mAnimator.resume();
        } else {
            startAnim();
        }
    }

    public void pauseAnim() {
        if (mAnimator != null) {
            mAnimator.pause();
        }
    }

    public void cancelAnim() {
        if (mAnimator != null) {
            mAnimator.cancel();
            mAnimator.removeAllUpdateListeners();
        }
    }
}