package com.adealink.weparty.commonui.widget

import android.animation.Animator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.adealink.weparty.R

/**
 * Created By: duxuefu
 * Creation Date: 2025/3/31
 * Description: 带进度条样式的按钮
 * 使用场景：
 * 1.长按录制视频；
 */
class CircleProgressButtonView : View {
    private var mBigCirclePaint: Paint? = null
    private var mSmallCirclePaint: Paint? = null
    private var mProgressCirclePaint: Paint? = null
    private var mHeight = 0 // 当前View的高
    private var mWidth = 0 // 当前View的宽
    private var mInitBitRadius = 0f
    private var mInitSmallRadius = 0f
    private var mBigRadius = 0f
    private var mSmallRadius = 0f
    private var mStartTime: Long = 0
    private var mEndTime: Long = 0
    private var isRecording = false // 录制状态
    private var isMaxTime = false // 达到最大录制时间
    private var mCurrentProgress = 0f // 当前进度

    private val mLongClickTime: Long = 500 // 长按最短时间(毫秒)
    private var mMaxTime = 10 * 1000 // 录制最大时间(毫秒)
    private var mMinTime = 0 // 录制最短时间(毫秒)
    private var mProgressColor = 0 // 进度条颜色
    private var mProgressW = 18f // 圆环宽度

    private var isPressed = false //当前手指处于按压状态
    private val mProgressAni by lazy { //圆弧进度变化
        ValueAnimator.ofFloat(0f, 360f).apply {
            // 📢：这里额外+300毫秒，主要是为了保证录制时间足够；
            // 因为摄像启动等耗时会导致录制时间小于<传入时间一点点，在时长向下取整时会少1s；
            // 实际示例：传入最大录制时长30s,录制结束视频时长2997毫秒。
            // 更精准的解法：按钮的动画在监听到录制Start时再启动，这就需要录制Event和按钮绑定。
            duration = (mMaxTime + 300).toLong()
        }
    }

    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?) {
        val a = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressButtonView)
        mMinTime = a.getInt(R.styleable.CircleProgressButtonView_minSeconds, 0) * 1000
        mMaxTime = a.getInt(R.styleable.CircleProgressButtonView_maxSeconds, 10) * 1000
        mProgressW = a.getDimension(R.styleable.CircleProgressButtonView_progressWidth, 12f)
        mProgressColor = a.getColor(
            R.styleable.CircleProgressButtonView_progressColor,
            Color.parseColor("#6ABF66")
        )
        a.recycle()
        initPaint()
    }

    private fun initPaint() {
        //初始画笔抗锯齿、颜色
        mBigCirclePaint = Paint(Paint.ANTI_ALIAS_FLAG)
        mBigCirclePaint?.color = Color.parseColor("#DDDDDD")

        mSmallCirclePaint = Paint(Paint.ANTI_ALIAS_FLAG)
        mSmallCirclePaint?.color = Color.parseColor("#FFFFFF")

        mProgressCirclePaint = Paint(Paint.ANTI_ALIAS_FLAG)
        mProgressCirclePaint?.color = mProgressColor
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        mWidth = MeasureSpec.getSize(widthMeasureSpec)
        mHeight = MeasureSpec.getSize(heightMeasureSpec)
        mBigRadius = mWidth / 2f * 0.75f
        mInitBitRadius = mBigRadius
        mSmallRadius = mBigRadius * 0.75f
        mInitSmallRadius = mSmallRadius
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        // 绘制外圆
        mBigCirclePaint?.let {
            canvas.drawCircle(mWidth / 2f, mHeight / 2f, mBigRadius, it)
        }
        // 绘制内圆
        mSmallCirclePaint?.let {
            canvas.drawCircle(mWidth / 2f, mHeight / 2f, mSmallRadius, it)
        }
        // 录制的过程中绘制进度条
        if (isRecording) drawProgress(canvas)
    }

    private fun drawProgress(canvas: Canvas) {
        mProgressCirclePaint?.strokeWidth = mProgressW
        mProgressCirclePaint?.style = Paint.Style.STROKE
        // 用于定义的圆弧的形状和大小的界限
        val oval = RectF(
            mWidth / 2f - (mBigRadius - mProgressW / 2),
            mHeight / 2f - (mBigRadius - mProgressW / 2),
            mWidth / 2f + (mBigRadius - mProgressW / 2),
            mHeight / 2f + (mBigRadius - mProgressW / 2)
        )
        // 根据进度画圆弧
        mProgressCirclePaint?.let {
            canvas.drawArc(oval, -90f, mCurrentProgress, false, it)
        }
    }

    private val mHandler: Handler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            when (msg.what) {
                WHAT_LONG_CLICK -> {
                    // 长按事件触发
                    onLongClickListener?.onLongClick()
                    // 内外圆动画，内圆缩小，外圆放大
                    startAnimation(
                        mBigRadius,
                        mBigRadius * 1.33f,
                        mSmallRadius,
                        mSmallRadius * 0.7f
                    )
                }
            }
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                isPressed = true
                mStartTime = System.currentTimeMillis()
                val mMessage = Message.obtain()
                mMessage.what = WHAT_LONG_CLICK
                mHandler.sendMessageDelayed(mMessage, mLongClickTime)
            }

            MotionEvent.ACTION_UP -> {
                isPressed = false
                isRecording = false
                mEndTime = System.currentTimeMillis()
                if (mEndTime - mStartTime < mLongClickTime) {
                    mHandler.removeMessages(WHAT_LONG_CLICK)
                    onClickListener?.onClick()
                } else {
                    startAnimation(mBigRadius, mInitBitRadius, mSmallRadius, mInitSmallRadius)
                    if (mProgressAni != null && mProgressAni.currentPlayTime < mMinTime && !isMaxTime) {
                        onLongClickListener?.onNoMinRecord()
                        mProgressAni.cancel()
                    } else {
                        //录制完成
                        if (!isMaxTime) {
                            onLongClickListener?.onRecordFinished()
                        }
                    }
                }
            }
        }
        return true
    }

    private fun startAnimation(bigStart: Float, bigEnd: Float, smallStart: Float, smallEnd: Float) {
        val bigObjAni = ValueAnimator.ofFloat(bigStart, bigEnd)
        bigObjAni.setDuration(150)
        bigObjAni.addUpdateListener { animation: ValueAnimator ->
            mBigRadius = animation.animatedValue as Float
            invalidate()
        }

        val smallObjAni = ValueAnimator.ofFloat(smallStart, smallEnd)
        smallObjAni.setDuration(150)
        smallObjAni.addUpdateListener { animation: ValueAnimator ->
            mSmallRadius = animation.animatedValue as Float
            invalidate()
        }

        bigObjAni.start()
        smallObjAni.start()

        smallObjAni.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator) {
                isRecording = false
            }

            override fun onAnimationEnd(animation: Animator) {
                // 开始绘制圆形进度
                if (isPressed) {
                    isRecording = true
                    isMaxTime = false
                    startProgressAnimation()
                }
            }

            override fun onAnimationCancel(animation: Animator) {
            }

            override fun onAnimationRepeat(animation: Animator) {
            }
        })
    }

    private fun startProgressAnimation() {
        mProgressAni.start()
        mProgressAni.addUpdateListener { animation: ValueAnimator ->
            mCurrentProgress = animation.animatedValue as Float
            invalidate()
        }

        mProgressAni.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator) {
            }

            override fun onAnimationEnd(animation: Animator) {
                // 录制动画结束时，即为录制全部完成
                if (onLongClickListener != null && isPressed) {
                    isPressed = false
                    isMaxTime = true
                    onLongClickListener?.onRecordFinished()
                    startAnimation(mBigRadius, mInitBitRadius, mSmallRadius, mInitSmallRadius)
                    //影藏进度进度条
                    mCurrentProgress = 0f
                    invalidate()
                }
            }

            override fun onAnimationCancel(animation: Animator) {
            }

            override fun onAnimationRepeat(animation: Animator) {
            }
        })
    }

    /**
     * @param maxSeconds 最大录制秒数
     */
    fun setMaxTime(maxSeconds: Int) {
        mMaxTime = maxSeconds * 1000
    }

    interface OnLongClickListener {
        fun onLongClick()

        // 未达到最小录制时间
        fun onNoMinRecord()

        // 录制完成
        fun onRecordFinished()
    }

    var onLongClickListener: OnLongClickListener? = null

    interface OnClickListener {
        fun onClick()
    }

    var onClickListener: OnClickListener? = null

    companion object {
        private const val WHAT_LONG_CLICK = 1
    }
}