package com.gh.gamecenter.common.view

import android.animation.ValueAnimator
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.RadioButton
import android.widget.RadioGroup
import androidx.core.content.ContextCompat
import com.gh.gamecenter.common.R
import com.gh.gamecenter.common.utils.dip2px
import splitties.views.dsl.core.add

class SegmentedFilterView : FrameLayout {

    private var mItemWidth = 0
    private var mItemHeight = 0
    private var mTextColor: ColorStateList? =
        ContextCompat.getColorStateList(context, R.color.game_collection_rg_button_selector)
    private var mTextSize = 10F
    private var mContainerBackground: Drawable? = null
    private var mIndicatorBackground: Drawable? = null
    private var mAnimationDuration = 200
    private var mContainerPadding = 1F.dip2px()

    private lateinit var mContainer: FrameLayout
    private lateinit var mRadioGroup: RadioGroup
    private lateinit var mIndicator: View
    private var mCallback: OnCheckedCallback? = null

    private var mItemList = listOf<String>()

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

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

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

    fun setTextColor(colorStateList: ColorStateList?) {
        if (::mRadioGroup.isInitialized) {
            for (i in 0 until mRadioGroup.childCount) {
                val radioBtn = mRadioGroup.getChildAt(i) as RadioButton
                radioBtn.setTextColor(colorStateList)
            }
        }
    }

    fun setContainerBackground(drawable: Drawable?) {
        background = drawable
    }

    fun setIndicatorBackground(drawable: Drawable?) {
        if (::mIndicator.isInitialized) {
            mIndicator.background = drawable
        }
    }

    private fun initView(attrs: AttributeSet?) {
        if (attrs != null) {
            val ta = context.obtainStyledAttributes(attrs, R.styleable.SegmentedFilterView)
            mContainerBackground =
                ta.getDrawable(R.styleable.SegmentedFilterView_containerBackground)
            mIndicatorBackground =
                ta.getDrawable(R.styleable.SegmentedFilterView_indicatorBackground)
            mContainerPadding = ta.getDimensionPixelSize(
                R.styleable.SegmentedFilterView_containerPadding,
                1F.dip2px()
            )
            mItemWidth = ta.getDimensionPixelSize(
                R.styleable.SegmentedFilterView_sfv_itemWidth,
                36F.dip2px()
            )
            mItemHeight = ta.getDimensionPixelSize(
                R.styleable.SegmentedFilterView_sfv_itemHeight,
                24F.dip2px()
            )
            mAnimationDuration = ta.getInt(R.styleable.SegmentedFilterView_animationDuration, 200)
            mTextColor = ta.getColorStateList(R.styleable.SegmentedFilterView_sfv_textColor)
            mTextSize = ta.getFloat(R.styleable.SegmentedFilterView_sfv_textSize, 10F)
            ta.recycle()
        }
        setPadding(mContainerPadding, mContainerPadding, mContainerPadding, mContainerPadding)
        if (mContainerBackground != null) background = mContainerBackground
        mContainer = FrameLayout(context)
        mIndicator = View(context).apply {
            background = mIndicatorBackground
        }
        mRadioGroup = RadioGroup(context).apply {
            gravity = Gravity.CENTER
            orientation = LinearLayout.HORIZONTAL
        }
        add(mContainer, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT))
        mContainer.add(mIndicator, LayoutParams(mItemWidth, mItemHeight))
        mContainer.add(
            mRadioGroup,
            LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
        )
    }

    fun setItemList(itemList: List<String>, defaultCheckPosition: Int) {
        mItemList = itemList
        mRadioGroup.removeAllViews()
        addRadioButton()
        post {
            setChecked(defaultCheckPosition)
        }
    }

    fun getItemList(): List<String> {
        return mItemList
    }

    fun performClick(position: Int) {
        if (position in 0 until mRadioGroup.childCount) {
            val radioButton = mRadioGroup.getChildAt(position) as RadioButton
            radioButton.isChecked = true
            startIndicatorAnimation(radioButton.x)
            mCallback?.onItemCheck(position)
        }
    }

    fun setChecked(position: Int) {
        if (position in 0 until mRadioGroup.childCount) {
            val radioButton = mRadioGroup.getChildAt(position) as RadioButton
            mIndicator.x = radioButton.x
            radioButton.isChecked = true
        }
    }

    fun getCurrentPosition(): Int {
        var position = 0
        for (i in 0 until mRadioGroup.childCount) {
            val radioButton = mRadioGroup.getChildAt(i) as RadioButton
            if (radioButton.isChecked) {
                position = i
                break
            }
        }
        return position
    }

    fun setOnCheckedCallback(callback: OnCheckedCallback) {
        mCallback = callback
        mRadioGroup.setOnCheckedChangeListener { _, checkId ->
            for (i in 0 until mRadioGroup.childCount) {
                val radioBtn = mRadioGroup.getChildAt(i)
                if (checkId == radioBtn.id && radioBtn.x != mIndicator.x) {
                    startIndicatorAnimation(radioBtn.x)
                    mCallback?.onItemCheck(i)
                }
            }
        }
    }

    private fun addRadioButton() {
        for (item in mItemList) {
            val radioButton = RadioButton(context).apply {
                background = null
                buttonDrawable = null
                text = item
                gravity = Gravity.CENTER
                textSize = mTextSize
                setTextColor(mTextColor)
                isChecked = false
            }
            mRadioGroup.add(radioButton, LinearLayout.LayoutParams(mItemWidth, mItemHeight))
        }
    }

    private fun startIndicatorAnimation(x: Float) {
        ValueAnimator.ofFloat(mIndicator.x, x).apply {
            interpolator = AccelerateDecelerateInterpolator()
            duration = mAnimationDuration.toLong()
            addUpdateListener {
                mIndicator.x = it.animatedValue as Float
            }
        }.start()
    }

    fun interface OnCheckedCallback {
        fun onItemCheck(position: Int)
    }
}