package com.base.scanqrclear.luma

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.graphics.Typeface
import android.util.AttributeSet
import android.view.View
import android.view.animation.OvershootInterpolator
import com.base.scanqrclear.R

class RoundProgressBar @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private var ringPaint: Paint = Paint()
    private var ringProgressPaint: Paint = Paint()
    private var textPaint: Paint = Paint()

    private var ringColor: Int
    private var ringProgressColor: Int
    private var textColor: Int

    private var textSize: Float
    private var ringWidth: Float

    private var max: Int = 100
    private var progress: Int = 0
    private var showTextProgress: Boolean = true
    private var styles: Int = 0
    private val STROKE = 0
    private val FULL = 1

    init {
        context.theme.obtainStyledAttributes(attrs, R.styleable.RoundProgressBar, defStyleAttr, 0)
            .apply {
                try {
                    ringColor = getColor(R.styleable.RoundProgressBar_ringColor, Color.GRAY)
                    ringProgressColor =
                        getColor(R.styleable.RoundProgressBar_ringProgressColor, Color.GREEN)
                    textColor = getColor(R.styleable.RoundProgressBar_textColor, Color.GREEN)
                    textSize = getDimension(R.styleable.RoundProgressBar_textSize, 16f)
                    ringWidth = getDimension(R.styleable.RoundProgressBar_ringWidth, 5f)
                    max = getInteger(R.styleable.RoundProgressBar_maxpro, 100)
                    progress = getInteger(R.styleable.RoundProgressBar_progresspro, 0)
                    showTextProgress =
                        getBoolean(R.styleable.RoundProgressBar_showTextProgress, true)
                    styles = getInt(R.styleable.RoundProgressBar_style, 0)
                } finally {
                    recycle()
                }
            }
        initPaint()
    }

    private fun initPaint() {
        ringPaint = Paint().apply {
            color = ringColor
            style = Paint.Style.STROKE
            strokeWidth = ringWidth
            isAntiAlias = true
        }

        ringProgressPaint = Paint().apply {
            color = ringProgressColor
            strokeWidth = ringWidth
            strokeCap = Paint.Cap.ROUND
            isAntiAlias = true
            when (styles) {
                STROKE -> style = Paint.Style.STROKE
                FULL -> style = Paint.Style.FILL_AND_STROKE
            }
        }

        textPaint = Paint().apply {
            color = textColor
            textSize = this@RoundProgressBar.textSize
            typeface = Typeface.DEFAULT_BOLD
        }
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        val xCenter = width / 2f
        val yCenter = height / 2f

        val radius = (xCenter - ringWidth / 2).toInt()
        canvas.drawCircle(xCenter, yCenter, radius.toFloat(), ringPaint)

        val rectF = RectF(xCenter - radius, yCenter - radius, xCenter + radius, yCenter + radius)
        when (styles) {
            STROKE -> canvas.drawArc(
                rectF, 270f,
                -(progress * 360 / max).toFloat(), false, ringProgressPaint
            )

            FULL -> if (progress != 0) canvas.drawArc(
                rectF, 270f,
                -(progress * 360 / 100).toFloat(), true, ringProgressPaint
            )
        }

        val text = "$progress%"
        val textWidth = textPaint.measureText(text)
        if (showTextProgress && progress != 0 && styles == STROKE) {
            canvas.drawText(text, xCenter - textWidth / 2, yCenter + textSize / 2, textPaint)
        }
    }

    fun getMax(): Int = max

    fun setMax(max: Int) {
        if (max < 0) throw IllegalArgumentException("max not less than 0")
        this.max = max
    }

    fun getProgress(): Int = progress

    fun setProgress(progress: Int) {
        if (progress < 0) throw IllegalArgumentException("progress not less than 0")
        if (progress > max) this.progress = max
        if (progress <= max) {
            this.progress = progress
            postInvalidate()
        }
    }

    fun setProgress(progress: Int, useAnimation: Boolean) {
        if (progress < 0) throw IllegalArgumentException("progress not less than 0")
        if (progress > max) this.progress = max
        if (useAnimation) {
            ValueAnimator.ofInt(0, progress).apply {
                addUpdateListener { animation ->
                    this@RoundProgressBar.progress = animation.animatedValue as Int
                    postInvalidate()
                }
                interpolator = OvershootInterpolator()
                duration = 1000
                start()
            }
        } else {
            this.progress = progress
            postInvalidate()
        }
    }

    fun getRingColor(): Int = ringColor

    fun setRingColor(ringColor: Int) {
        this.ringColor = ringColor
    }

    fun getRingProgressColor(): Int = ringProgressColor

    fun setRingProgressColor(ringProgressColor: Int) {
        this.ringProgressColor = ringProgressColor
    }

    fun getTextColor(): Int = textColor

    fun setTextColor(textColor: Int) {
        this.textColor = textColor
    }

    fun getTextSize(): Float = textSize

    fun setTextSize(textSize: Float) {
        this.textSize = textSize
    }

    fun getRingWidth(): Float = ringWidth

    fun setRingWidth(ringWidth: Float) {
        this.ringWidth = ringWidth
    }
}