package com.adealink.weparty.im.session.widget

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.os.Parcelable
import android.util.AttributeSet
import android.view.View
import androidx.core.graphics.toColorInt
import com.adealink.weparty.im.R

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

    companion object {
        private val WAVE_HEADER_STYLE = listOf(
            0, 0, 0
        )
        private val WAVE_REPEAT_STYLE = listOf(
            0, 20, 30, 60, 100, 60, 100, 80, 60, 30, 20, 0
            //100, 100, 100, 100, 100, 100, 100, 80, 100, 100, 100, 100 //测试用
        )
    }

    private var waveList = mutableListOf<Int>()

    /**
     * 线间距 px
     */
    private var lineSpace: Float = 5f

    /**
     * 线宽 px
     */
    private var lineWidth: Float = 5f


    /**
     * 线颜色
     */
    private var lineHintColor: Int = "#661D2129".toColorInt()

    private var lineColor: Int = "#1D2129".toColorInt()

    private var lineHintPaint: Paint = Paint().apply {
        isAntiAlias = true
        style = Paint.Style.FILL
        strokeCap = Paint.Cap.ROUND
    }

    private var linePaint: Paint = Paint().apply {
        isAntiAlias = true
        style = Paint.Style.FILL
        strokeCap = Paint.Cap.ROUND
    }

    private var cursorWidth: Float = 10f

    private var cursorColor: Int = "#1789FF".toColorInt()

    private var cursorPaint: Paint = Paint().apply {
        color = cursorColor
        isAntiAlias = true
        style = Paint.Style.FILL
        strokeCap = Paint.Cap.ROUND
    }

    private var playAnimator = ValueAnimator.ofFloat(0f, 1f)

    private var playProgress: Float = 0f

    @Volatile
    var isStart: Boolean = false
        private set

    init {
        attrs?.let {
            val typedArray = context.theme.obtainStyledAttributes(
                attrs,
                R.styleable.MessageSoundPlayView, 0, 0
            )

            lineWidth =
                typedArray.getDimension(
                    R.styleable.MessageSoundPlayView_message_sound_play_line_width,
                    lineWidth
                )
            lineSpace =
                typedArray.getDimension(
                    R.styleable.MessageSoundPlayView_message_sound_play_line_space,
                    lineSpace
                )
            lineColor =
                typedArray.getInt(
                    R.styleable.MessageSoundPlayView_message_sound_play_line_color,
                    lineColor
                )

            cursorWidth =
                typedArray.getDimension(
                    R.styleable.MessageSoundPlayView_message_sound_play_cursor_width,
                    cursorWidth
                )

            cursorColor =
                typedArray.getInt(
                    R.styleable.MessageSoundPlayView_message_sound_play_cursor_color,
                    cursorColor
                )
            typedArray.recycle()
        }
    }

    fun setColor(lineColor: Int, lineHintColor: Int, cursorColor: Int) {
        this.lineColor = lineColor
        this.lineHintColor = lineHintColor
        this.cursorColor = cursorColor
        postInvalidate()
    }


    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        if (waveList.isEmpty()) {
            updateWaveList(right - left, bottom - top)
        }
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        updateWaveList(w, h)
    }

    private fun updateWaveList(width: Int, height: Int) {
        var count = (width - cursorWidth) / (lineWidth + lineSpace)
        val newWaveList = mutableListOf<Int>()
        for (i in 0 until WAVE_HEADER_STYLE.size) {
            if (count <= 0) {
                break
            }
            count--
            newWaveList.add(WAVE_HEADER_STYLE[i])
        }
        while (count > 0) {
            for (i in 0 until WAVE_REPEAT_STYLE.size) {
                if (count <= 0) {
                    break
                }
                count--
                newWaveList.add(WAVE_REPEAT_STYLE[i])
            }
        }
        waveList = newWaveList
        invalidate()
    }

    /**
     * 开始
     */
    fun start(duration: Long) {
        if (isStart) {
            playAnimator.cancel()
        }
        isStart = true
        playProgress = 0f
        playAnimator.duration = duration
        playAnimator.addUpdateListener {
            playProgress = it.getAnimatedValue() as Float
            invalidate()
        }
        playAnimator.start()
    }

    /**
     * @param allTime 总时长
     * @param duration 剩余时长
     * @param speed 播放速度
     */
    fun start(allTime: Long, duration: Long, speed: Float) {
        if (isStart) {
            playAnimator.cancel()
            playAnimator = null
        }
        isStart = true
        playProgress = duration * 1f / allTime
        playAnimator = ValueAnimator.ofFloat(playProgress, 1f)
        playAnimator.duration = ((allTime - duration) / speed).toLong()

        playAnimator.addUpdateListener {
            playProgress = it.getAnimatedValue() as Float
            invalidate()
        }
        playAnimator.start()
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        drawLine(canvas)
        drawCursor(canvas)
    }

    private fun drawLine(canvas: Canvas) {
        if (waveList.isEmpty()) {
            return
        }
        linePaint.strokeWidth = lineWidth
        linePaint.color = lineColor

        lineHintPaint.strokeWidth = lineWidth
        lineHintPaint.color = lineHintColor

        for (i in waveList.indices) {
            var startX = cursorWidth / 2f
            var startY = 0f
            var endX = 0f
            var endY = 0f

            val lineHeight = waveList[i] / 100.0 * measuredHeight

            startX = startX + i * (lineSpace + lineWidth) + lineWidth / 2
            endX = startX

            startY = (measuredHeight / 2 - lineHeight / 2).toFloat()
            endY = (measuredHeight / 2 + lineHeight / 2).toFloat()

            val cursorX = cursorEndX()
            if (cursorX > startX) {
                canvas.drawLine(
                    startX,
                    startY,
                    endX,
                    endY,
                    linePaint
                )
            } else {
                canvas.drawLine(
                    startX,
                    startY,
                    endX,
                    endY,
                    lineHintPaint
                )
            }
        }
    }

    private fun drawCursor(canvas: Canvas) {
        cursorPaint.strokeWidth = cursorWidth
        cursorPaint.color = cursorColor

        val offsetX = (measuredWidth - cursorWidth) * playProgress

        val radius = cursorWidth / 2f

        val left = 0f + offsetX
        val right = left + cursorWidth
        val top = (measuredHeight / 2) - radius
        val bottom = (measuredHeight / 2) + radius

        canvas.drawOval(
            left, top, right, bottom, cursorPaint
        )
    }

    /**
     * 锚点中心
     */
    private fun cursorCenterX(): Float {
        val offsetX = (measuredWidth - cursorWidth) * playProgress
        return offsetX + cursorWidth / 2f
    }

    private fun cursorEndX(): Float {
        val offsetX = (measuredWidth - cursorWidth) * playProgress
        return offsetX + cursorWidth
    }

    /**
     * 停止 onDestroy call
     */
    fun stop() {
        isStart = false
        playProgress = 0f
        playAnimator.cancel()
        waveList.clear()
        postInvalidate()
    }

    override fun onSaveInstanceState(): Parcelable? {
        //TODO onSaveInstanceState
        return super.onSaveInstanceState()
    }

    override fun onRestoreInstanceState(state: Parcelable?) {
        //TODO onRestoreInstanceState
        super.onRestoreInstanceState(state)
    }

}