package com.ns.yc.ycprogresslib;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Typeface;
import android.graphics.Xfermode;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;


/**
 * <pre>
 *     @author 杨充
 *     blog  : https://github.com/yangchong211
 *     time  : 2016/2/10
 *     desc  : 自定义进度条,新芽,沙丘大学下载进度条
 *     revise: 参考案例:夏安明博客http://blog.csdn.net/xiaanming/article/details/10298163
 *             案例地址:https://github.com/yangchong211
 * </pre>
 */
public class RingProgressBar extends View {

    private int percent;                        //当前百分比
    private int progressMax;                    //最大进度
    private int dotColor;                       //颜色
    private int dotBgColor;                     //背景颜色
    private int showMode;                       //进度条的样式

    private float percentTextSize;              //百分比字体大小
    private int percentTextColor;               //百分比字体颜色
    private int percentThinPadding;

    private String unitText;
    private float unitTextSize;
    private int unitTextColor;
    private int unitTextAlignMode;
    public static final int UNIT_TEXT_ALIGN_MODE_DEFAULT = 0;
    public static final int UNIT_TEXT_ALIGN_MODE_CN = 1;
    public static final int UNIT_TEXT_ALIGN_MODE_EN      = 2;


    private Paint mPaint;
    private float mSin_1;                       // sin(1°)
    private Typeface mPercentTypeface;

    private float mCenterX;
    private float mCenterY;

    private Canvas mCanvas;
    private Bitmap mBitmap;
    private Xfermode mClearCanvasXfermode;
    private Xfermode mPercentThinXfermode;

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

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

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


        // 其他准备工作
        mSin_1 = (float) Math.sin(Math.toRadians(1)); // 求sin(1°)。角度需转换成弧度
        mPaint = new Paint();
        mPaint.setAntiAlias(true);      // 消除锯齿

        //百分比字体类型,设置成默认值
        mPercentTypeface = Typeface.DEFAULT;

        mClearCanvasXfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
        if (percentThinPadding != 0) {
            mPercentThinXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
        }

    }

    private void initialize(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RingProgressBar);
        // 获取自定义属性值或默认值
        progressMax = ta.getInteger(R.styleable.RingProgressBar_progressMax, 100);
        dotColor = ta.getColor(R.styleable.RingProgressBar_dotColor, Color.WHITE);
        dotBgColor = ta.getColor(R.styleable.RingProgressBar_dotBgColor, Color.GRAY);
        showMode = ta.getInt(R.styleable.RingProgressBar_showMode, ProgressBarUtils.RingShowMode.SHOW_MODE_PERCENT);

        if (showMode != ProgressBarUtils.RingShowMode.SHOW_MODE_NULL) {
            percentTextSize = ta.getDimension(R.styleable.RingProgressBar_percentTextSize, ProgressBarUtils.dp2px(context,30));
            percentTextColor = ta.getInt(R.styleable.RingProgressBar_percentTextColor, Color.WHITE);
            percentThinPadding = ta.getInt(R.styleable.RingProgressBar_percentThinPadding, 0);

            unitText = ta.getString(R.styleable.RingProgressBar_unitText);
            unitTextSize = ta.getDimension(R.styleable.RingProgressBar_unitTextSize, percentTextSize);
            unitTextColor = ta.getInt(R.styleable.RingProgressBar_unitTextColor, Color.BLACK);
            unitTextAlignMode = ta.getInt(R.styleable.RingProgressBar_unitTextAlignMode, UNIT_TEXT_ALIGN_MODE_DEFAULT);

            if (unitText == null) {
                unitText = "%";
            }
        }
        ta.recycle();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 绘制外围圆点进度
        drawCircleDot(mCanvas);
        if (showMode != ProgressBarUtils.RingShowMode.SHOW_MODE_NULL) {
            // 绘制百分比+单位
            drawPercentUnit(mCanvas);
        }
        canvas.drawBitmap(mBitmap, 0, 0, null);
    }


    /**
     * 绘制圆点进度
     * @param canvas 画布
     */
    private void drawCircleDot(Canvas canvas) {
        // 先清除上次绘制的
        mPaint.setXfermode(mClearCanvasXfermode);
        mCanvas.drawPaint(mPaint);
        mPaint.setXfermode(null);

        // 计算圆点半径
        float outerRadius = (getWidth() < getHeight() ? getWidth() : getHeight()) / 2f;
        mCenterX = getWidth() / 2f;
        mCenterY = getHeight() / 2f;

        // outerRadius = innerRadius + dotRadius
        // sin((360°/200)/2) = sin(0.9°) = dotRadius / innerRadius;
        // 为了让圆点饱满一些,把角度0.9°增加0.1°到1°
        float dotRadius = mSin_1 * outerRadius / (1 + mSin_1);


        // 画进度
        mPaint.setColor(dotColor);
        mPaint.setStyle(Paint.Style.FILL);
        int count = 0;
        // 1.1 当前进度
        while (count++ < percent) {
            mCanvas.drawCircle(mCenterX, mCenterY - outerRadius + dotRadius, dotRadius, mPaint);
            mCanvas.rotate(3.6f, mCenterX, mCenterY);
        }
        // 1.2 未完成进度
        mPaint.setColor(dotBgColor);
        count--;
        while (count++ < 100) {
            mCanvas.drawCircle(mCenterX, mCenterY - outerRadius + dotRadius, dotRadius, mPaint);
            mCanvas.rotate(3.6f, mCenterX, mCenterY);
        }
    }

    /**
     * 绘制百分比和单位
     * @param canvas 画布
     */
    private void drawPercentUnit(Canvas canvas) {
        // 测量百分比和单位的宽度
        mPaint.setTypeface(mPercentTypeface);
        mPaint.setTextSize(percentTextSize);
        float percentTextWidth = mPaint.measureText(percent + "");

        mPaint.setTypeface(Typeface.DEFAULT);
        mPaint.setTextSize(unitTextSize);
        float unitTextWidth = mPaint.measureText(unitText);
        Paint.FontMetrics fm_unit = mPaint.getFontMetrics();

        float textWidth = percentTextWidth + unitTextWidth;

        float baseline = 0;
        if (showMode == ProgressBarUtils.RingShowMode.SHOW_MODE_PERCENT) {
            float textHeight = percentTextSize > unitTextSize ? percentTextSize : unitTextSize;
            // 计算Text垂直居中时的baseline
            mPaint.setTextSize(textHeight);
            Paint.FontMetrics fm = mPaint.getFontMetrics();
            // 字体在垂直居中时,字体中间就是centerY,加上字体实际高度的一半就是descent线,减去descent就是baseline线的位置(fm中以baseline为基准)
            baseline = mCenterY + (fm.descent - fm.ascent)/2 - fm.descent;
        }

        // 2.1 画百分比
        mPaint.setTypeface(mPercentTypeface);
        mPaint.setTextSize(percentTextSize);
        mPaint.setColor(percentTextColor);
        canvas.drawText(percent + "", mCenterX - textWidth / 2, baseline, mPaint);

        // 2.1.1 对百分比瘦身
        if (percentThinPadding != 0) {
            // 使用橡皮擦擦除
            mPaint.setXfermode(mPercentThinXfermode);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(percentThinPadding);
            canvas.drawText(percent + "", mCenterX - textWidth / 2, baseline, mPaint);
            mPaint.setXfermode(null);
            mPaint.setStyle(Paint.Style.FILL);
        }

        // 2.2 画单位
        mPaint.setTypeface(Typeface.DEFAULT);
        mPaint.setTextSize(unitTextSize);
        mPaint.setColor(unitTextColor);
        // 单位对齐方式
        switch (unitTextAlignMode) {
            case UNIT_TEXT_ALIGN_MODE_CN:
                baseline -= fm_unit.descent / 4;
                break;
            case UNIT_TEXT_ALIGN_MODE_EN:
                baseline -= fm_unit.descent * 2/3;
                break;
            default:
                break;
        }
        canvas.drawText(unitText, mCenterX - textWidth / 2 + percentTextWidth, baseline, mPaint);
    }


    public synchronized void setProgressMax(int progressMax) {
        if (progressMax < 0 || progressMax >100) {
            throw new IllegalArgumentException("progressMax mustn't smaller than 0 or 100");
        }
        this.progressMax = progressMax;
    }

    /**
     * 设置进度
     * 同步,允许多线程访问
     * @param progress 进度
     */
    public synchronized void setProgress(int progress) {
        if (progress < 0 || progress > progressMax) {
            throw new IllegalArgumentException(String.format(getResources().getString(R.string.progress_out_of_range), progressMax));
        }
        percent = progress * 100 / progressMax;
        postInvalidate();       // 可以直接在子线程中调用,而invalidate()必须在主线程(UI线程)中调用
    }

    /**
     * 设置更新的进度条颜色
     * @param dotColor                      int
     */
    public void setDotColor(@ColorInt int dotColor) {
        this.dotColor = dotColor;
        invalidate();
    }

    /**
     * 设置未更新部分的进度条颜色
     * @param dotBgColor                    int
     */
    public void setDotBgColor(@ColorInt int dotBgColor) {
        this.dotBgColor = dotBgColor;
        invalidate();
    }

    /**
     * 设置展示的类型
     * @param showMode                      @ProgressBarUtils.RingShowModeType
     */
    public void setShowMode(@ProgressBarUtils.RingShowModeType int showMode) {
        this.showMode = showMode;
    }

    /**
     * 设置百分比文字大小
     * @param percentTextSize               percentTextSize
     */
    public void setPercentTextSize(float percentTextSize) {
        this.percentTextSize = percentTextSize;
        invalidate();
    }

    /**
     * 设置百分比文字颜色
     * @param percentTextColor              percentTextColor
     */
    public void setPercentTextColor(@ColorInt int percentTextColor) {
        this.percentTextColor = percentTextColor;
        invalidate();
    }


    /**
     * 设置百分比间距
     * @param percentThinPadding            padding
     */
    public void setPercentThinPadding(int percentThinPadding) {
        this.percentThinPadding = percentThinPadding;
        invalidate();
    }

    /**
     * 设置单位的文字内容
     * @param unitText                      unitText
     */
    public void setUnitText(@NonNull String unitText) {
        this.unitText = unitText;
        invalidate();
    }

    /**
     * 设置单位的文字大小
     * @param unitTextSize                  size
     */
    public void setUnitTextSize(float unitTextSize) {
        this.unitTextSize = unitTextSize;
        invalidate();
    }

    /**
     * 设置单位的文字颜色
     * @param unitTextColor                 color
     */
    public void setUnitTextColor(@ColorInt int unitTextColor) {
        this.unitTextColor = unitTextColor;
        invalidate();
    }

}