package com.gh.gamecenter.common.view

import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.gh.gamecenter.common.R
import com.gh.gamecenter.common.databinding.ViewPkBinding
import com.gh.gamecenter.common.entity.PKEntity
import com.gh.gamecenter.common.utils.setDebouncedClickListener
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.core.utils.doOnEnd
import com.gh.gamecenter.core.utils.doOnStart
import java.math.BigDecimal

class PKView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null): ConstraintLayout(context, attrs) {
    private val binding: ViewPkBinding
    private var data: PKEntity? = null
    var onPositiveClick: (() -> Unit)? = null
    var onNegativeClick: (() -> Unit)? = null

    init {
        val view = LayoutInflater.from(context).inflate(R.layout.view_pk, this, true)
        binding = ViewPkBinding.bind(view)
        initView()
    }

    private fun initView() {
        binding.positiveTv.setDebouncedClickListener {
            if (data?.isExpired == false) {
                onPositiveClick?.invoke()
            }
        }
        binding.negativeTv.setDebouncedClickListener {
            if (data?.isExpired == false) {
                onNegativeClick?.invoke()
            }
        }
    }

    fun isInitialized() = data != null

    fun setData(entity: PKEntity) {
        if (entity != data) {
            data = entity
            updateView()
        }
    }

    fun updateView() {
        if (data == null) return

        if (data!!.shouldShowResult) {
            showResult()
        } else {
            showPK()
        }
    }

    private fun showPK() {
        binding.positiveTv.text = data?.option1?.text
        binding.negativeTv.text = data?.option2?.text
        binding.resultContainer.isVisible = false
        binding.pkContainer.isVisible = true
        binding.pkContainer.alpha = if (data!!.isExpired) 0.3F else 1F
    }

    private fun showResult() {
        if (data == null) return
        if (data?.option1?.num == 0 && data?.option2?.num == 0) return

        updateResultView()
        binding.pkContainer.isVisible = false
    }

    private fun updateResultView() {
        if (data == null) return
        if (data?.option1?.num == 0 && data?.option2?.num == 0) return

        binding.positivePercentTv.setTextColor(if (data!!.isVotePositive) R.color.white.toColor(context) else R.color.text_theme.toColor(context))
        binding.negativePercentTv.setTextColor(if (data!!.isVoteNegative) R.color.white.toColor(context) else R.color.secondary_red.toColor(context))
        binding.positiveResultTv.setTextColor(R.color.text_theme.toColor(context))
        binding.negativeResultTv.setTextColor(R.color.secondary_red.toColor(context))
        binding.positiveResultTv.alpha = if (data!!.isExpired) 0.3F else 1F
        binding.negativeResultTv.alpha = if (data!!.isExpired) 0.3F else 1F

        binding.trapezoidProgressBar.show(data!!.isVotePositive, data!!.isVoteNegative, data!!.progress)
        binding.positiveResultTv.text = data?.positiveResultText
        binding.negativeResultTv.text = data?.negativeResultText
        val positivePercent = data!!.progress.toBigDecimal().multiply(BigDecimal(100)).setScale(1)
        binding.positivePercentTv.isGone = positivePercent.toFloat() == 0F
        binding.negativePercentTv.isGone = positivePercent.toFloat() == 100F
        binding.positivePercentTv.text = "${positivePercent}%"
        binding.negativePercentTv.text = "${BigDecimal(100).subtract(positivePercent)}%"
        binding.resultContainer.isVisible = true
    }

    fun vote(isPositive: Boolean) {
        if (data == null) return

        data!!.isJoin = true
        data!!.userOption = if (isPositive) "option1" else "option2"
        if (isPositive) {
            data!!.option1.num++
        } else {
            data!!.option2.num++
        }
    }

    fun showResultWithAnimation() {
        if (data == null) return
        if (data?.option1?.num == 0 && data?.option2?.num == 0) return

        val pkAlphaAnimator = ValueAnimator.ofFloat(1F, 0F).apply {
            addUpdateListener { va -> binding.pkContainer.alpha = (va.animatedValue as Float) }
        }
        val resultAlphaAnimator = ValueAnimator.ofFloat(0F, 1F).apply {
            addUpdateListener { va -> binding.resultContainer.alpha = (va.animatedValue as Float) }
        }
        AnimatorSet().apply {
            duration = 1000L
            playTogether(pkAlphaAnimator, resultAlphaAnimator)
            doOnStart {
                updateResultView()
                binding.resultContainer.alpha = 0F
            }
            doOnEnd {
                showResult()
            }
        }.start()
    }
}