package com.gh.gamecenter.feature.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.text.TextPaint
import android.util.AttributeSet
import android.view.View
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.sp2px

import com.gh.gamecenter.common.R
import com.gh.gamecenter.common.utils.toColor

import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.tan

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

    private val customStrokeWidth = 1F.dip2px().toFloat()
    private val defaultCornerRadius = 8F.dip2px().toFloat()

    private val bottomLeftAngle = Math.toRadians(80.0).toFloat()

    private val mainPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val progressPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)

    private val progressColor = R.color.primary_theme.toColor(context)
    private val defaultBackgroundColor = Color.WHITE

    private val inset = customStrokeWidth / 2

    private var safeHeight = 0F
    private var safeWidth = 0F

    private var text = "9000K/S"
    private var textSize = 14F.sp2px().toFloat()
    private var baseline = 0

    private var progress = 0F

    init {
        progressPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        textPaint.textSize = textSize
        textPaint.style = Paint.Style.FILL_AND_STROKE
        textPaint.textAlign = Paint.Align.CENTER
    }

    /**
     * Set the progress of the trapezoid
     * @param progress The progress of the trapezoid. Must be between 0 and 1
     */
    fun setProgress(progress: Float) {
        this.progress = progress
        invalidate()
    }

    fun setText(text: String) {
        this.text = text
        invalidate()
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)

        safeHeight = height.toFloat() - inset
        safeWidth = width.toFloat() - inset

        val fontMetrics = textPaint.fontMetricsInt
        baseline = (height - fontMetrics.bottom - fontMetrics.top) / 2
    }

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

        val saveLayer = canvas.saveLayer(0f, 0f, width.toFloat(), height.toFloat(), null, Canvas.ALL_SAVE_FLAG)

        drawStrokeAndBackground(canvas, mainPaint)
        drawProgress(canvas, progressPaint, progress)

        drawText(canvas, textPaint, progress)

        canvas.restoreToCount(saveLayer)
    }

    private fun drawText(canvas: Canvas, paint: Paint, progress: Float) {
        val progressWidth = width * progress + inset

        // Draw the text in two parts: one for the progress part and one for the remaining part
        canvas.save()

        // Clip the progress part
        canvas.clipRect(0f, 0f, progressWidth, safeHeight)
        paint.color = Color.WHITE
        canvas.drawText(text, getWidth() / 2F, baseline.toFloat(), paint)

        canvas.restore()
        canvas.save()

        // Clip the remaining part
        canvas.clipRect(progressWidth, 0f, safeWidth, safeHeight)
        paint.color = progressColor
        canvas.drawText(text, getWidth() / 2F, baseline.toFloat(), paint)

        canvas.restore()
    }

    private fun drawStrokeAndBackground(canvas: Canvas, paint: Paint) {
        // Calculate the x displacement for the bottom left angle
        val topLeftX = safeHeight / tan(bottomLeftAngle)

        val insetPadding = inset
        val cosValue = defaultCornerRadius * cos(bottomLeftAngle)
        val sinValue = defaultCornerRadius * sin(bottomLeftAngle)

        // Create the path for the trapezoid
        val path = Path().apply {
            moveTo(insetPadding + defaultCornerRadius, safeHeight) // Bottom-left point

            quadTo(
                insetPadding,
                safeHeight,
                cosValue + insetPadding,
                safeHeight - (sinValue + insetPadding)
            ) // Bottom-left corner (rounded corner

            lineTo(
                topLeftX - cosValue,
                insetPadding + sinValue
            ) // Top-left point

            quadTo(
                topLeftX,
                insetPadding,
                topLeftX + cosValue + defaultCornerRadius,
                insetPadding
            ) // Top-left control point and end point

            lineTo(safeWidth - defaultCornerRadius, insetPadding) // Top-right point

            quadTo(
                safeWidth,
                insetPadding,
                safeWidth,
                insetPadding + defaultCornerRadius
            ) // Top-right corner (rounded corner)

            lineTo(safeWidth, safeHeight - defaultCornerRadius) // Bottom-right point

            quadTo(
                safeWidth,
                safeHeight,
                safeWidth - defaultCornerRadius,
                safeHeight
            ) // Bottom-right corner (rounded corner

            close()
        }

        paint.color = defaultBackgroundColor
        paint.style = Paint.Style.FILL

        // Draw the trapezoid background
        canvas.drawPath(path, paint)

        paint.color = progressColor
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = customStrokeWidth

        // Draw the trapezoid stroke
        canvas.drawPath(path, paint)
    }

    private fun drawProgress(canvas: Canvas, paint: Paint, progress: Float) {
        // Calculate the x displacement for the bottom left angle
        val progressWidth = width * progress

        // Create the path for the trapezoid
        val path = Path().apply {
            moveTo(inset, safeHeight) // Bottom-left point
            lineTo(inset, inset)
            lineTo(progressWidth + inset, inset)
            lineTo(progressWidth + inset, safeHeight)

            close()
        }

        paint.color = progressColor

        // Draw the trapezoid
        canvas.drawPath(path, paint)
    }
}
