package com.isidroid.slider.ext

import android.content.Context
import android.view.LayoutInflater
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.compose.ui.graphics.toArgb
import com.google.android.material.slider.Slider
import com.isidroid.slider.SliderColor
import com.isidroid.slider.SliderOption
import com.isidroid.ui.slider.R

internal class ExtendedSliderView(context: Context?) : LinearLayout(context) {
    private val sliderView: Slider
    private val labelContainer: FrameLayout
    private val layoutInflater = LayoutInflater.from(context)

    init {
        orientation = VERTICAL
        layoutInflater.inflate(R.layout.layout_slider, this, true)

        sliderView = findViewById(R.id.sliderView)
        labelContainer = findViewById(R.id.labelContainer)
    }


    inline fun update(
        crossinline updateAnswer: (value: String?, isManual: Boolean) -> Unit,
        options: List<SliderOption> = emptyList(),
        isEnabled: Boolean = true,
        currentValue: String? = null,
        isAnswered: Boolean = false,
        allowSubmitDefaultAnswer: Boolean = false,
        colors: SliderColor = SliderColor.getDefaults(),
    ) = apply {
        val colorTrackActive = colors.trackActive.toArgb()
        val colorTrackDefault = colors.trackDefault.toArgb()
        val colorLabelActive = colors.labelActive.toArgb()
        val colorLabelDefault = colors.labelDefault.toArgb()

        var isValueChanged = false
        val mutex = Object()

        createValues(options, currentValue)

        sliderView.isEnabled = isEnabled
        sliderView.postDelayed({
            val coordinates = sliderView.calculateCoordinates()

            val labelViewList = coordinates.mapIndexed { index, offsetX ->
                val option = options.getOrNull(index)

                createSliderLabel(
                    inflater = layoutInflater,
                    parent = labelContainer,
                    text = option?.text,
                    tag = option,
                    offset = offsetX,
                    isActive = option?.isActive == true,
                    labelDefaultColor = colorLabelDefault,
                    labelActiveColor = colorLabelActive
                )
            }

            if (allowSubmitDefaultAnswer)
                updateAnswer(options.getOrNull(sliderView.value.toInt())?.text, false)

            sliderView.updateSliderColor(trackActiveColor = colorTrackActive, trackDefaultColor = colorTrackDefault, isEnabled = isEnabled)

            displayActiveSliderLabel(
                labelViewList = labelViewList,
                labelActiveColor = colorLabelActive,
                labelDefaultColor = colorLabelDefault
            ) { tag -> findItem(tag, sliderView.value.toInt(), options) }

            sliderView.addOnChangeListener { _, index, _ ->
                displayActiveSliderLabel(
                    labelViewList = labelViewList,
                    labelActiveColor = colorLabelActive,
                    labelDefaultColor = colorLabelDefault
                ) { tag -> findItem(tag, index.toInt(), options) }
            }

            sliderView.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
                override fun onStartTrackingTouch(slider: Slider) {
                    synchronized(mutex) {
                        if (!isValueChanged) {
                            isValueChanged = true
                            sliderView.updateSliderColor(trackActiveColor = colorTrackActive, trackDefaultColor = colorTrackDefault, isEnabled = isEnabled)
                        }
                    }
                }

                override fun onStopTrackingTouch(slider: Slider) {
                    updateAnswer(options.getOrNull(slider.value.toInt())?.text, true)
                }
            })

        }, 100)
    }

    private fun createValues(valueList: List<SliderOption>, currentValue: String?) {
        sliderView.isEnabled = isEnabled
        sliderView.valueFrom = 0f
        sliderView.valueTo = (valueList.size - 1).toFloat()
        sliderView.value = valueList.indexOfFirst { it.text == currentValue }.takeIf { it >= 0 }?.toFloat() ?: 0f
    }
}