package com.abbidot.tracker.widget

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.DashPathEffect
import android.graphics.Paint
import android.graphics.Path
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.Region
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.core.content.ContextCompat
import com.abbidot.baselibrary.util.AppUtils
import com.abbidot.baselibrary.util.Utils
import com.abbidot.tracker.R
import com.abbidot.tracker.constant.ConstantInt
import com.abbidot.tracker.util.ViewUtil
import com.qmuiteam.qmui.util.QMUIDisplayHelper
import kotlin.math.min


/**
 *Created  by .yzq on 2024/2/4/004.
 * @link
 * @description:圆环刻度尺
 */
class RingScaleView : View {

    private lateinit var mContext: Context
    private var mWidth = 0
    private var mHeight = 0

    private lateinit var mOutCirclePaint: Paint
    private lateinit var mScalePaint: Paint
    private lateinit var mFillPaint: Paint
    private lateinit var mTextPaint: Paint
    private lateinit var mDashedPaint: Paint
    private lateinit var mDragPaint: Paint
    private lateinit var mPathPaint: Paint

    private lateinit var mRectF: RectF
    private lateinit var mRect: Rect

    private lateinit var mDragPath: Path
    private lateinit var mPathRegion: Region

    //最外面的圆需要刻度的个数
    private val mOutCircleScale = 360

    //最外面的圆的半径
    private var mOutCircleRadius = 0f

    //内圆的半径
    private var mInsideCircleRadius = 0f

    //显示结果的圆半径
    private var mShowResultCircleRadius = 0f
    private var mDragCircleRadius = 0f

    //最外面圆的线的长度
    private val mOutCircleStrokeHeight = QMUIDisplayHelper.dpToPx(18).toFloat()

    //最外面圆的线的宽度
    private var mOutCircleStrokeWidth = 0f

    private lateinit var mMinimumString: String
    private lateinit var mRecommencedString: String

    //选中的值
    private var mValue = 30

    //配合动画,每次画百分几
    private var mAnimatedPercent = 0f

    constructor(context: Context) : super(context) {
        init(context, null)
    }

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context, attrs, defStyleAttr
    ) {
        init(context, attrs)
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init(context, attrs)
    }

    private fun init(context: Context, attrs: AttributeSet?) {
        mContext = context
        initAttrs(context, attrs)

        //禁用硬件加速,防止返回到界面多次执行onDraw
        setLayerType(LAYER_TYPE_SOFTWARE, null)

        mMinimumString = context.getString(R.string.txt_minimum)
        mRecommencedString = context.getString(R.string.txt_recommenced)

        mOutCirclePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
            style = Paint.Style.STROKE
            //虚线长度
            strokeWidth = mOutCircleStrokeHeight
            color = ContextCompat.getColor(context, R.color.line_color1)
        }
        mScalePaint = Paint().apply {
            color = ContextCompat.getColor(context, R.color.data_black_color)
            strokeWidth = QMUIDisplayHelper.dpToPx(1).toFloat()
        }
        mFillPaint = Paint()
        mTextPaint = Paint().apply {
            color = ContextCompat.getColor(context, R.color.block_color2)
            textSize = QMUIDisplayHelper.sp2px(context, 8).toFloat()
        }
        mDashedPaint = Paint().apply {
            color = ContextCompat.getColor(context, R.color.line_color1)
        }
        mDragPaint = Paint().apply {
            strokeWidth = QMUIDisplayHelper.dpToPx(1).toFloat()
            color = ContextCompat.getColor(context, R.color.select_color)
            style = Paint.Style.STROKE
        }
        mPathPaint = Paint().apply {
            color = ContextCompat.getColor(context, R.color.select_color2)
        }

        mDragPath = Path()
        mPathRegion = Region()
        mRectF = RectF()
        mRect = Rect()
    }

    private fun initAttrs(context: Context, attrs: AttributeSet?) {
        if (null == attrs) {

        }
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mShowResultCircleRadius = QMUIDisplayHelper.dpToPx(28).toFloat()
        mDragCircleRadius = mShowResultCircleRadius / 2f
        //外圆的半径,虚线的长度默认圆内外各占一半,圆的外边距
        mOutCircleRadius =
            width.coerceAtMost(height) / 2f - mOutCirclePaint.strokeWidth / 2f - QMUIDisplayHelper.dpToPx(
                20
            )
        //计算出周长
        val circumference = 2 * Math.PI * mOutCircleRadius

        //根据虚线+空白间隔=圆的周长(这里默认虚线宽度和空白间隔一样大小)
        val dashOutGapSize = circumference / (mOutCircleScale * 2)
        mOutCircleStrokeWidth = dashOutGapSize.toFloat()
        mOutCirclePaint.pathEffect = DashPathEffect(
            floatArrayOf(
                mOutCircleStrokeWidth, mOutCircleStrokeWidth
            ), 0f
        )

        mInsideCircleRadius = mOutCircleRadius - mOutCirclePaint.strokeWidth / 2f

        mDashedPaint.strokeWidth = mScalePaint.strokeWidth * 2
        val dashSpace = mOutCircleStrokeWidth * 3
        mDashedPaint.pathEffect = DashPathEffect(
            floatArrayOf(dashSpace, dashSpace), 0f
        )
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        mWidth = measuredWidth
        mHeight = measuredHeight
    }


    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.apply {
            startDraw(this)
        }
    }

    private fun startDraw(canvas: Canvas) {
        val halfWith = mWidth / 2f
        val halfHeight = mHeight / 2f
        canvas.apply {
            //画虚线
            val lineStartY = halfHeight - mInsideCircleRadius
            drawLine(halfWith, lineStartY, halfWith, halfHeight, mDashedPaint)

            //outScaleRectF
            mRectF.apply {
                left = halfWith - mOutCircleRadius
                top = halfHeight - mOutCircleRadius
                right = halfWith + mOutCircleRadius
                bottom = halfHeight + mOutCircleRadius
            }
            mOutCirclePaint.color = ContextCompat.getColor(mContext, R.color.select_color2)
            drawArc(mRectF, -90f, mValue.toFloat(), false, mOutCirclePaint)
            mOutCirclePaint.color = ContextCompat.getColor(mContext, R.color.black25)
            drawArc(mRectF, -90f, -(360f - mValue), false, mOutCirclePaint)

            //填充推荐的颜色区域
            mRectF.apply {
                left = halfWith - mInsideCircleRadius
                top = lineStartY
                right = halfWith + mInsideCircleRadius
                bottom = halfHeight + mInsideCircleRadius
            }
            mFillPaint.color = ContextCompat.getColor(mContext, R.color.yellow_color10)
            drawArc(mRectF, -90f, 30f, true, mFillPaint)
            mFillPaint.color = ContextCompat.getColor(mContext, R.color.green_color10)
            drawArc(mRectF, -60f, 180f, true, mFillPaint)
            //写区域文字
            save()
            rotate(-75f, halfWith, halfHeight)
            mTextPaint.color = ContextCompat.getColor(context, R.color.block_color2)
            mTextPaint.textSize = QMUIDisplayHelper.sp2px(context, 8).toFloat()
            //文字宽度
            var textWidth = mTextPaint.measureText(mMinimumString)
            var fontMetrics = mTextPaint.fontMetrics
            //文字高度
            var textHeight = fontMetrics.bottom - fontMetrics.top
            drawText(
                mMinimumString,
                halfWith + textWidth + textHeight / 2,
                halfHeight + textHeight / 3,
                mTextPaint
            )
            restore()
            drawText(
                mRecommencedString,
                halfWith - mShowResultCircleRadius / 3,
                halfHeight + mShowResultCircleRadius + textHeight * 2,
                mTextPaint
            )

            //画圆里面的大小刻度
            save()
            var curRotation = 0
            val scaleTempY = lineStartY + mOutCircleStrokeHeight / 2
            for (i in 0 until 24) {
                val y2 = if (curRotation % 90 == 0) {
                    mScalePaint.color = ContextCompat.getColor(mContext, R.color.data_black_color)
                    scaleTempY + QMUIDisplayHelper.dpToPx(6)    //+240
                } else {
                    mScalePaint.color = ContextCompat.getColor(mContext, R.color.block_color2)
                    scaleTempY
                }
                drawLine(halfWith, lineStartY, halfWith, y2, mScalePaint)
                curRotation += 15
                rotate(15f, halfWith, halfHeight)
            }
            restore()

            //画最外层的刻度
            mTextPaint.textSize = QMUIDisplayHelper.sp2px(mContext, 12).toFloat()
            mTextPaint.color = ContextCompat.getColor(mContext, R.color.select_color3)
            val cR = (min(mWidth, height) - QMUIDisplayHelper.dpToPx(10)) / 2f
            for (i in 0 until 360 step 45) {
                textWidth = mTextPaint.measureText("$i")
                fontMetrics = mTextPaint.fontMetrics
                textHeight = fontMetrics.bottom - fontMetrics.top
                val cXy = getPointOnCircle(halfWith, halfHeight, cR, i.toDouble())
                if (i == 0) {
                    drawText("0", cXy[0] - textWidth / 2f, cXy[1] + textHeight / 2f, mTextPaint)
                } else {
                    drawText("$i", cXy[0] - textWidth / 2f, cXy[1], mTextPaint)
                }
            }
            mTextPaint.textSize = QMUIDisplayHelper.sp2px(mContext, 10).toFloat()
            textWidth = mTextPaint.measureText("30")
            fontMetrics = mTextPaint.fontMetrics
            textHeight = fontMetrics.bottom - fontMetrics.top
            val cXy = getPointOnCircle(halfWith, halfHeight, cR, 30.0)
            drawText("30", cXy[0] - textWidth / 2f, cXy[1] + textHeight / 5f, mTextPaint)

            //画可拖动的圆
            val circleXY = getPointOnCircle(
                halfWith, halfHeight, mOutCircleRadius, (mValue * mAnimatedPercent).toDouble()
            )
            drawLine(halfWith, halfHeight, circleXY[0], circleXY[1], mDashedPaint)
            //外层圆环形
            drawCircle(
                circleXY[0], circleXY[1], mDragCircleRadius, mDragPaint
            )
            val dragCircleRadius = mDragCircleRadius - mDragPaint.strokeWidth / 2
            mDragPath.reset()
            mDragPath.addCircle(
                circleXY[0], circleXY[1], dragCircleRadius, Path.Direction.CW
            )
            mRect.apply {
                left = 0
                top = 0
                right = mWidth
                bottom = mHeight
            }
            mPathRegion.setEmpty()
            //取出rect和mDragPath交集区域
            mPathRegion.setPath(mDragPath, Region(mRect))
            drawPath(mPathRegion.boundaryPath, mPathPaint)
            //圆心相同的矩形
//            val rect1 = Rect(
//                (halfWith - dragCircleRadius).toInt(),
//                (circleY + dragCircleRadius).toInt(),
//                (halfWith + dragCircleRadius).toInt(),
//                (circleY - dragCircleRadius).toInt()
//            )

            //画显示值的白色圆
            mFillPaint.color = ContextCompat.getColor(mContext, R.color.white)
            drawCircle(halfWith, halfHeight, mShowResultCircleRadius, mFillPaint)

            //画出值
            val valueString = "$mValue"
            mTextPaint.textSize = QMUIDisplayHelper.sp2px(mContext, 18).toFloat()
            mTextPaint.color = ContextCompat.getColor(mContext, R.color.data_black_color)
            //文字宽度
            textWidth = mTextPaint.measureText(valueString)
            drawText(valueString, halfWith - textWidth / 2, halfHeight, mTextPaint)
            val minString = "min"
            mTextPaint.textSize = QMUIDisplayHelper.sp2px(mContext, 12).toFloat()
            mTextPaint.color = ContextCompat.getColor(mContext, R.color.block_color2)
            //文字宽度
            textWidth = mTextPaint.measureText(minString)
            fontMetrics = mTextPaint.fontMetrics
            //文字高度
            textHeight = fontMetrics.bottom - fontMetrics.top
            drawText(
                minString, halfWith - textWidth / 2, halfHeight + textHeight / 1.3f, mTextPaint
            )
        }
    }

    /**
     *求圆上某个点的坐标
     * @angle 角度是以圆的右方开始计算角度，顺时针增加
     */
    private fun getPointOnCircle(
        centerX: Float, centerY: Float, radius: Float, angle: Double
    ): FloatArray {
        //转换角度从圆的正上方开始，顺时针增加
        return Utils.getPointOnCircleArc(centerX, centerY, radius, angle - 90)
    }

    fun getValue() = mValue

    fun setValue(value: Int) {
        mValue = if (value >= ConstantInt.MinSportGoal) value
        else ConstantInt.DefaultSportGoal
        ViewUtil.instance.setValueAnimator(0f, 100f) {
            mAnimatedPercent = it.animatedValue as Float / 100
            postInvalidate()
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when (event!!.action) {
            MotionEvent.ACTION_DOWN -> {
                val x = event.x
                val y = event.y
                if (mPathRegion.contains(x.toInt(), y.toInt())) {
                    mDragCircleRadius = mShowResultCircleRadius / 2f + AppUtils.dpToPx(3.9f)
                    return true
                }
                return false
            }

            MotionEvent.ACTION_MOVE -> {
                val x = event.x
                val y = event.y
                //限制左右滑动超过
                val point = getPointOnCircle(mWidth / 2f, mHeight / 2f, mOutCircleRadius, 30.0)
                //限制右半边圆部分
                if (mValue == 30) {
                    if (x < point[0]) return false
                }
                //限制左边圆部分
                else if (mValue in 270..360) {
                    if (x > mWidth / 2f) return false
                }
                //获取以圆右方为0度的角度
                val slipAngle = Utils.getAngleFromCenter(x, y, mWidth / 2f, mHeight / 2f)
                mValue = (slipAngle + 90).toInt()
                if (mValue in 1..30) {
                    mValue = 30
                    return false
                } else if (mValue < 0) {
                    mValue += 360
                } else if (mValue == 360 || mValue == 0) {
                    mValue = 360
                    return false
                }
                invalidate()
            }

            MotionEvent.ACTION_UP -> {
                mDragCircleRadius = mShowResultCircleRadius / 2f
                invalidate()
            }
        }
        return super.onTouchEvent(event)
    }

    /**
     * 解决滑动冲突
     */
    override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
        //禁止父容器拦截子元素需要的事件。
        parent.requestDisallowInterceptTouchEvent(true)
        return super.dispatchTouchEvent(event)
    }
}