package com.dahe.mylibrary.weight;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.TextView;

import com.dahe.mylibrary.R;

/**
 * @ClassName CircleBarView
 * @Author john
 * @Date 2024/2/7 16:08
 * @Description TODO
 */
public class CircleBarView extends View {
    private Paint rPaint;//绘制矩形的画笔
    private Paint progressPaint;//绘制圆弧的画笔
    private Paint anchorPaint, anchorBgPaint;//锚点
    private float anchorRadius, anchorBgRadius;
    private int anchorColor, anchorBgColor;
    private CircleBarAnim anim;
    private Paint bgPaint;//绘制背景圆弧的画笔
    private float progress;//可以更新的进度条数值
    private float maxProgress;//进度条最大值
    private float progressSweepAngle;//进度条圆弧扫过的角度
    private int startAngle;//背景圆弧的起始角度
    private float sweepAngle;//背景圆弧扫过的角度
    private RectF mRectF;//绘制圆弧的矩形区域
    private float barWidth;//圆弧进度条宽度
    private int defaultSize;//自定义View默认的宽高
    private int[] progressColors;//进度条圆弧颜色
    private int bgColor;//背景圆弧颜色
    private SweepGradient sweepGradient;//进度条颜色使用渐变色
    private LinearGradient linearGradient;
    private float circleWidth, circleHeight;
    private float xDiff;

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

    private void init(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleBarView);
        int color1 = typedArray.getColor(R.styleable.CircleBarView_progress_color1, Color.RED);
        int color2 = typedArray.getColor(R.styleable.CircleBarView_progress_color2, color1);
        int color3 = typedArray.getColor(R.styleable.CircleBarView_progress_color3, color2);//写法巧妙
        progressColors = new int[]{color1, color1, color2, color3};//必须得4个，
        bgColor = typedArray.getColor(R.styleable.CircleBarView_bg_color, Color.GRAY);//默认为灰色
        circleWidth = typedArray.getDimension(R.styleable.CircleBarView_circle_width, dip2px(context, 200));//默认为0
        circleHeight = typedArray.getDimension(R.styleable.CircleBarView_circle_height, dip2px(context, 80));//默认为360
        barWidth = typedArray.getDimension(R.styleable.CircleBarView_bar_width, dip2px(context, 10));//默认为10dp
        anchorRadius = typedArray.getDimension(R.styleable.CircleBarView_anchor_radius, dip2px(context, 5));
        anchorBgRadius = typedArray.getDimension(R.styleable.CircleBarView_anchor_bg_radius, dip2px(context, 8.5f));
        anchorColor = typedArray.getColor(R.styleable.CircleBarView_anchor_color, Color.RED);
        anchorBgColor = typedArray.getColor(R.styleable.CircleBarView_anchor_bg_color, Color.GREEN);
        maxProgress = typedArray.getInt(R.styleable.CircleBarView_progress_max, 100);
        typedArray.recycle();//typedArray用完之后需要回收，防止内存泄漏

        rPaint = new Paint();
        rPaint.setStyle(Paint.Style.STROKE);//只描边，不填充
        rPaint.setColor(Color.RED);

        progressPaint = new Paint();
        progressPaint.setStyle(Paint.Style.STROKE);//只描边，不填充

        progressPaint.setStrokeWidth(barWidth);
        progressPaint.setAntiAlias(true);//设置抗锯齿
        progressPaint.setStrokeCap(Paint.Cap.ROUND);

        //锚点
        anchorPaint = new Paint();
        anchorPaint.setAntiAlias(true);//设置抗锯齿
        anchorPaint.setColor(anchorColor);
        //锚点背景
        anchorBgPaint = new Paint();
        anchorBgPaint.setAntiAlias(true);//设置抗锯齿

        int a = Color.alpha(anchorBgColor);
        int r = Color.red(anchorBgColor);
        int g = Color.green(anchorBgColor);
        int b = Color.blue(anchorBgColor);
//        LogSuperUtil.i("circle_bar", "a=" + a + ",r=" + r + ",g=" + g + ",b=" + b);
        anchorBgPaint.setColor(Color.rgb(r, g, b));
        anchorBgPaint.setAlpha(a);
        /*raw
        anchorBgPaint.setColor(anchorBgColor);
        anchorBgPaint.setAlpha(185);*/

        anim = new CircleBarAnim();
        bgPaint = new Paint();
        bgPaint.setStyle(Paint.Style.STROKE);
        bgPaint.setColor(bgColor);
        bgPaint.setStrokeWidth(barWidth);
        bgPaint.setAntiAlias(true);
        bgPaint.setStrokeCap(Paint.Cap.ROUND);
        mRectF = new RectF();

        //
        defaultSize = dip2px(context, 200);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //进度条的总轮廓
        canvas.drawArc(mRectF, startAngle, sweepAngle, false, bgPaint);
        float outCircleRadius = mRectF.width() / 2;//带宽度的进度条的中线半径

        if (sweepGradient == null) {
            float centerX = (mRectF.left + mRectF.right) / 2;
            float centerY = (mRectF.top + mRectF.bottom) / 2;
            //
            int rotateDiff = 30;//为了解决圆弧开头出的圆角颜色不正常的问题，30度够用了吧
            int rotateDegree = startAngle - rotateDiff;
            float sweepEndPosition = (rotateDiff + sweepAngle * progress / maxProgress * 1.0f) / 360;
//            LogSuperUtil.i("circle_bar", "startAngle=" + startAngle + ",sweepEndPosition=" + sweepEndPosition);

            float[] positions = {0, rotateDiff * 1.0f / 360, sweepEndPosition, 1};
            sweepGradient = new SweepGradient(centerX, centerY, progressColors, positions);
            Matrix rotateMatrix = new Matrix();
            //设置渐变色
            rotateMatrix.setRotate(rotateDegree, centerX, centerY);//180表示从左侧开始往上渐变
            sweepGradient.setLocalMatrix(rotateMatrix);//sweepGradient默认是从0度方向开始渐变的，所以要逆转一下。
            progressPaint.setShader(sweepGradient);
        }
        /*
        if(linearGradient==null) {
            linearGradient = new LinearGradient(0, 0, outCircleRadius*2, 0, progressColors,
                    null, LinearGradient.TileMode.CLAMP);
            progressPaint.setShader(linearGradient);
        }*/
        //进度条
        canvas.drawArc(mRectF, startAngle, progressSweepAngle, false, progressPaint);
        float anchorAngle = progressSweepAngle + (startAngle - 180);

        float anchorCoordRedius = outCircleRadius - barWidth / 2;
        double cosValue = Math.cos(Math.toRadians(anchorAngle));
        double sinValue = Math.sin(Math.toRadians(anchorAngle));

        float diffByAnchor = anchorBgRadius - barWidth / 2;//x和y的偏移正好都是这个
        //float cx=(float)(outCircleRadius-cosValue*anchorCoordRedius+diffByAnchor);
        float cx = (float) (outCircleRadius - cosValue * outCircleRadius + anchorBgRadius);
        //float cy=(float)(outCircleRadius-sinValue*anchorCoordRedius+diffByAnchor);
        float cy = (float) (outCircleRadius - sinValue * outCircleRadius + anchorBgRadius);
        canvas.drawCircle(cx - xDiff, cy, anchorRadius, anchorPaint);//锚点小圆
        canvas.drawCircle(cx - xDiff, cy, anchorBgRadius, anchorBgPaint);//锚点背景大圆
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //int height=measureSize(defaultSize,heightMeasureSpec);
        //int width=measureSize(defaultSize,widthMeasureSpec);
        //startAngle是计算出来的，因为弦的这种，没法通过观察直接得出圆弧的起始角度
        //通过数学计算得知x
        //x是圆心（圆弧所在的圆的圆心）到弦（也就是圆弧的底部）的垂直距离
        float x = (circleWidth * circleWidth - 4 * circleHeight * circleHeight) / (8 * circleHeight);
        //画圆弧用到的圆的半径
        float r = x + circleHeight;
        //int r=(int)(circleWidth/2/Math.cos(Math.toRadians(startAngle-180)));
        //弦长/2/半径=cos(startAngle-180)
        //(startAngle-180)
        double asin = Math.asin(circleWidth / 2 / r);
        //LogSuperUtil.i("circle_bar","asin="+asin);
        int a = (int) Math.toDegrees(asin);
        //LogSuperUtil.i("circle_bar","a="+a);
        startAngle = 180 + (90 - a);
        sweepAngle = 2 * a;
        //int min=Math.max(width,height);//获取View最短边的长度
        int width = (int) (Math.sqrt(Math.pow(r + anchorBgRadius, 2) - Math.pow(x, 2)) * 2 + 0.5f + anchorBgRadius);//圆弧的宽度
        width = (int) (2 * (circleWidth / 2 + anchorBgRadius) + 0.5f);
        int height = (int) (circleHeight + anchorBgRadius + 0.5f + anchorBgRadius);
        //height=width;
        xDiff = r - circleWidth / 2;//画布是从最左边开始画圆且显示的，不偏移的话，显示的效果不对。
//        LogSuperUtil.i("circle_bar", "xDiff=" + xDiff);
        setMeasuredDimension(width, height);
        if (Math.min(width, height) >= barWidth * 2) {//这里简单限制了圆弧的最大宽度
            //1.mRectF决定着圆画在哪个框框里面
            //2.mRectF在当前View中，但不是完全占据当前View
            //3.弧度的粗细画的时候是均分到圆半径线的两侧的
            //4.之所以矩形设置的四个点有偏移，是因为有弧度宽度。
            //因为锚点也有宽度，点再次做调整.
            //mRectF.set(barWidth/2,barWidth/2,min-barWidth/2,min-barWidth/2);
            float diffByAnchor = anchorBgRadius - barWidth / 2;//受锚点影响需要修正的偏移
            //是整个圆的矩形，不是弧形区域所在的矩形
            mRectF.set(barWidth / 2 + diffByAnchor - xDiff, barWidth / 2 + diffByAnchor, barWidth / 2 + diffByAnchor + 2 * r - xDiff, barWidth / 2 + diffByAnchor + 2 * r);
        }
    }

    private int measureSize(int defaultSize, int measureSpec) {
        int result = defaultSize;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
//            LogSuperUtil.i("circle_bar", "=EXACTLY");
            result = specSize;
        } else if (specMode == MeasureSpec.AT_MOST) {
//            LogSuperUtil.i("circle_bar", "=AT_MOST");
            result = Math.min(result, specSize);
        } else {
//            LogSuperUtil.i("circle_bar", "=defaultSize");
        }
        return result;
    }

    private TextView textView;
    private OnAnimationListener onAnimationListener;

    public class CircleBarAnim extends Animation {
        public CircleBarAnim() {

        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            super.applyTransformation(interpolatedTime, t);
            progressSweepAngle = interpolatedTime * sweepAngle * progress / maxProgress;//这里计算进度条的比例
            postInvalidate();
            if (textView != null && onAnimationListener != null) {
                textView.setText(onAnimationListener.howToChangeText(interpolatedTime, progress, maxProgress));
            }
        }
    }

    /**
     * 设置显示文字的TextView
     *
     * @param textView
     */
    public void setTextView(TextView textView) {
        this.textView = textView;
    }
    /*
    * circleBarView.setOnAnimationListener(new CircleBarView.OnAnimationListener() {
	@Override
	public String howToChangeText(float interpolatedTime, float progressNum, float maxNum) {
		DecimalFormat decimalFormat=new DecimalFormat("0.00");
		String s = decimalFormat.format(interpolatedTime * progressNum / maxNum * 100) + "%";
		return s;
	}
});*/


    public interface OnAnimationListener {
        /**
         * 如何处理要显示的文字内容
         *
         * @param interpolatedTime 从0渐变成1，到1时结束动画
         * @param progressNum      进度条数值
         * @param maxNum           进度条最大值
         * @return
         */
        String howToChangeText(float interpolatedTime, float progressNum, float maxNum);
    }

    //写个方法给外部调用，用来设置动画时间
    public void setProgress(float progress, int time) {
        anim.setDuration(time);
        this.startAnimation(anim);
        this.progress = progress;
    }

    public static int dip2px(Context context, float dpValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    public static int px2dip(Context context, float pxValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    /**
     * //extraDistance比较小时，TextView离圆弧很近，是正常，因为TextView是从其自身的左上角开始渲染。
     *
     * @param sweepAnglePercent
     * @param extraDistance
     * @return
     */
    public float getAngleX(float sweepAnglePercent, int extraDistance) {
        float outCircleRadius = mRectF.width() / 2 + barWidth / 2;//带宽度的进度条的外圆半径
        float diffByAnchor = anchorBgRadius - barWidth / 2;//x和y的偏移正好都是这个
        float x = (float) (outCircleRadius + diffByAnchor - Math.cos(Math.toRadians(startAngle - 180 + sweepAnglePercent * sweepAngle)) * (outCircleRadius + dip2px(getContext(), extraDistance)) - xDiff);
        return x;
    }

    private static final String TAG = "circle_bar";

    /**
     * 在当前View中的y坐标
     * （注意，TextView渲染的时候，这个坐标是作为TextView控件的左上角进行渲染。
     * 所以，extraDistance小的话，显示的结果TextView可能还在当前View的内部呢，但TextView的左上角是在圆外部的。
     *
     * @param sweepAnglePercent
     * @param extraDistance     从外圆算的往外扩展的距离，不是从锚点背景边缘往外扩展。
     * @return
     */
    public float getAngleY(float sweepAnglePercent, int extraDistance) {
        float outCircleRadius = mRectF.width() / 2 + barWidth / 2;//带宽度的进度条的外圆半径
        float diffByAnchor = anchorBgRadius - barWidth / 2;//x和y的偏移正好都是这个
        float coordA = startAngle - 180 + sweepAnglePercent * sweepAngle;
//        LogSuperUtil.i("circle_bar", "coordA=" + coordA);
        float coordY = (float) Math.sin(Math.toRadians(coordA)) * (outCircleRadius + dip2px(getContext(), extraDistance));
//        LogSuperUtil.i("circle_bar", "coordY=" + coordY);
        float tempR = outCircleRadius + diffByAnchor;
//        LogSuperUtil.i("circle_bar", "tempR=" + tempR + ",=" + circleWidth);//CircleWidth是圆弧宽度
//        LogSuperUtil.i("circle_bar", "mRectF.width()/2=" + mRectF.width() / 2);
        float y = (float) (tempR - coordY);
        return y;
    }
}
