package com.secspace.lib.common.function.view;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 应用使用时间进度条
 */
public class TimeProgress extends View {

    private Paint bgPaint;

    private Paint textPaint;

    private int mWidth;
    private int mHeight;

    private List<Integer> times = new ArrayList<>();
    private List<Integer> paintColors = new ArrayList<>();
    private float allTime = 0F;
    private float animationValue;
    private float cylindricalStartLeft;
    private float indicatorMargin;

    /**
     * 进度动画
     */
    private ValueAnimator progressAnimator;

    /**
     * 动画执行时间
     */
    private int duration = 1000;
    /**
     * 动画延时启动时间
     */
    private int startDelay = 500;

    /**
     * 进度条画笔的宽度
     */
    private int progressPaintWidth;

    private int progressHeight;
    private int textHeight;

    /**
     * 柱状图距提示文字的高度
     */
    private int tipsMargin;
    private int textSize;

    /**
     * 进度条背景颜色
     */
    private int bgColor = 0xFFf66b12;
    /**
     * 进度条颜色
     */
    private int progressColor = 0xFFf66b12;

    private RectF bgRectF = new RectF();

    /**
     * 圆角矩形的圆角半径
     */
    private int roundRectRadius;

    private int paddingLeft;
    private int paddingTop;
    private int paddingRight;
    private int paddingBottom;

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

    public TimeProgress(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TimeProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
        initPaint();
        initTextPaint();
        times.add(10);
        times.add(20);
        times.add(80);
        times.add(50);
        Comparator<Integer> reverseComparator = Collections.reverseOrder();
        Collections.sort(times, reverseComparator);
        paintColors.add(0xFF13A6FA);
        paintColors.add(0xFF9BFA13);
        paintColors.add(0xFFFAB613);
        paintColors.add(0xFFE5E5E5);
        allTime = 160;
    }

    /**
     * 初始化画笔宽度及view大小
     */
    private void init() {
        progressPaintWidth = dp2px(5);
        progressHeight = dp2px(15);
        roundRectRadius = dp2px(3);
        indicatorMargin = dp2px(1);
        tipsMargin = progressHeight;
        textSize = dp2px(12);
    }


    private void initPaint() {
        bgPaint = getPaint(progressPaintWidth, bgColor, Paint.Style.FILL);
    }

    /**
     * 初始化文字画笔
     */
    private void initTextPaint() {
        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(progressColor);
        textPaint.setTextSize(textSize);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setAntiAlias(true);
    }

    private int getTextHeight(String text, Paint paint) {
        Rect rect = new Rect();
        paint.getTextBounds(text, 0, text.length(), rect);
        return rect.height();
    }

    private int getTextWidth(String text, Paint paint) {
        Rect rect = new Rect();
        paint.getTextBounds(text, 0, text.length(), rect);
        return rect.width();
    }

    /**
     * 统一处理paint
     *
     * @param strokeWidth 画笔宽度
     * @param color       颜色
     * @param style       风格
     * @return paint
     */
    private Paint getPaint(int strokeWidth, int color, Paint.Style style) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(strokeWidth);
        paint.setColor(color);
        paint.setAntiAlias(true);
        paint.setStyle(style);
        return paint;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        parameterAssignment();
        setMeasuredDimension(measureWidth(widthMode, width), measureHeight(heightMode, height));
    }

    /**
     * 测量宽度
     *
     * @param mode
     * @param width
     * @return
     */
    private int measureWidth(int mode, int width) {
        switch (mode) {
            case MeasureSpec.UNSPECIFIED:
            case MeasureSpec.AT_MOST:
                break;
            case MeasureSpec.EXACTLY:
                mWidth = width;
                break;
        }
        return mWidth;
    }

    public void setWidth(int width) {
        mWidth = width;
    }

    /**
     * 测量高度
     *
     * @param mode
     * @param height
     * @return
     */
    private int measureHeight(int mode, int height) {
        switch (mode) {
            case MeasureSpec.UNSPECIFIED:
            case MeasureSpec.AT_MOST:
                textHeight = getTextHeight("measureHeight", textPaint);
                mHeight = progressPaintWidth + progressHeight + tipsMargin + textHeight * 2 + paddingTop + paddingBottom;
                break;
            case MeasureSpec.EXACTLY:
                mHeight = height;
                break;
        }
        return mHeight;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 初始化width，padding等参数
        parameterAssignment();
        // 绘制横向柱状图
        drawHorizontalCylindrical(canvas);
        drawIndicator(canvas);
    }

    private void drawIndicator(Canvas canvas) {
        // 平分后每份的长度
        float share = mWidth / times.size();
        float x, y;
        for (int i = 0; i < times.size(); i++) {
            int time = times.get(i);
            String text = time + "分钟";
            textPaint.setColor(0xff000000);
            bgPaint.setColor(paintColors.get(i));
            float textHeight = getTextHeight(text, textPaint);
            float textWidth = getTextWidth(text, textPaint);

            x = share * i + share / 2;
            if (i == 0) {
                x = x + paddingLeft;
            }

            y = textHeight + tipsMargin + progressHeight + paddingLeft;
            canvas.drawRect(x - textWidth, y - textHeight + indicatorMargin, x - textWidth + textHeight, y + indicatorMargin, bgPaint);
            canvas.drawText(text, x, y, textPaint);
            canvas.drawText(text, x, y + textHeight + tipsMargin / 3, textPaint);
        }
    }

    private void drawHorizontalCylindrical(Canvas canvas) {
        for (int i = 0; i < times.size(); i++) {
            int time = times.get(i);
            float rate = time / allTime;
            if (i == 0) {
                bgRectF.left = cylindricalStartLeft + paddingLeft;
            } else {
                bgRectF.left = cylindricalStartLeft + 10;
            }
            bgPaint.setColor(paintColors.get(i));

            bgRectF.top = paddingTop;
            bgRectF.right = mWidth * rate * animationValue / 100 + cylindricalStartLeft;
            bgRectF.bottom = bgRectF.top + progressHeight;
            if (i == times.size() - 1) {
                bgRectF.right = mWidth * rate * animationValue / 100 - paddingRight + cylindricalStartLeft;
            }
            cylindricalStartLeft = bgRectF.right;
            canvas.drawRoundRect(bgRectF, roundRectRadius, roundRectRadius, bgPaint);
        }
        cylindricalStartLeft = 0;
    }

    public void initAnimation() {
        progressAnimator = ValueAnimator.ofFloat(0, 100);
        progressAnimator.setDuration(duration);
        progressAnimator.setStartDelay(startDelay);
        progressAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                animationValue = (float) valueAnimator.getAnimatedValue();
                invalidate();
            }
        });
        if (!progressAnimator.isStarted()) {
            progressAnimator.start();
        }
    }

    private void parameterAssignment() {
        mWidth = getMeasuredWidth();
        paddingLeft = getPaddingLeft();
        paddingTop = getPaddingTop();
        paddingRight = getPaddingRight();
        paddingBottom = getPaddingBottom();
    }

    /**
     * 格式化数字(保留一位小数)
     *
     * @param money
     * @return
     */
    public static String formatNum(int money) {
        DecimalFormat format = new DecimalFormat("0");
        return format.format(money);
    }

    /**
     * dp 2 px
     *
     * @param dpVal
     */
    protected int dp2px(int dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, getResources().getDisplayMetrics());
    }

    /**
     * sp 2 px
     *
     * @param spVal
     * @return
     */
    protected int sp2px(int spVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spVal, getResources().getDisplayMetrics());
    }
}
