package com.aletheia.app.ui.reader.tts

import android.content.Context
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.LinearLayout
import android.widget.SeekBar
import android.widget.Spinner
import android.widget.TextView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.util.Locale
import kotlin.math.roundToInt

object ReaderSpeechSettingsDialog {
    fun show(context: Context, controller: ReaderSpeechController) {
        val density = context.resources.displayMetrics.density
        val content = LinearLayout(context).apply {
            orientation = LinearLayout.VERTICAL
            val horizontal = (24 * density).roundToInt()
            val vertical = (8 * density).roundToInt()
            setPadding(horizontal, vertical, horizontal, vertical)
        }
        val voiceTitle = TextView(context).apply {
            text = "Голос Vosk TTS 0.9"
            textSize = 15f
            setPadding(0, 16, 0, 4)
        }
        val voice = Spinner(context).apply {
            adapter = ArrayAdapter(
                context,
                android.R.layout.simple_spinner_dropdown_item,
                ReaderSpeechController.VOICES
            )
            setSelection(controller.speakerId)
        }
        content.addView(voiceTitle)
        content.addView(voice)
        val rateValue = TextView(context)
        val rate = slider(
            context = context,
            label = "Темп чтения",
            value = controller.rate,
            min = ReaderSpeechController.MIN_RATE,
            max = ReaderSpeechController.MAX_RATE,
            valueView = rateValue,
            parent = content
        )
        val pitchValue = TextView(context)
        val pitch = slider(
            context = context,
            label = "Высота голоса",
            value = controller.pitch,
            min = ReaderSpeechController.MIN_PITCH,
            max = ReaderSpeechController.MAX_PITCH,
            valueView = pitchValue,
            parent = content
        )
        val pauseValue = TextView(context)
        val pause = slider(
            context = context,
            label = "Паузы на знаках препинания",
            value = controller.pauseScale,
            min = ReaderSpeechController.MIN_PAUSE_SCALE,
            max = ReaderSpeechController.MAX_PAUSE_SCALE,
            valueView = pauseValue,
            parent = content
        )
        val articulationValue = TextView(context)
        val articulation = slider(
            context = context,
            label = "Разборчивость слов и букв",
            value = controller.articulationScale,
            min = ReaderSpeechController.MIN_ARTICULATION_SCALE,
            max = ReaderSpeechController.MAX_ARTICULATION_SCALE,
            valueView = articulationValue,
            parent = content
        )

        MaterialAlertDialogBuilder(context)
            .setTitle("Озвучивание книги")
            .setMessage("Все параметры применяются к встроенному офлайн-голосу. Настройки меняются плавно.")
            .setView(content)
            .setNegativeButton("Отмена", null)
            .setPositiveButton("Сохранить") { _, _ ->
                controller.updateSettings(
                    progressToValue(rate.progress, ReaderSpeechController.MIN_RATE, ReaderSpeechController.MAX_RATE),
                    progressToValue(pitch.progress, ReaderSpeechController.MIN_PITCH, ReaderSpeechController.MAX_PITCH),
                    progressToValue(
                        pause.progress,
                        ReaderSpeechController.MIN_PAUSE_SCALE,
                        ReaderSpeechController.MAX_PAUSE_SCALE
                    ),
                    progressToValue(
                        articulation.progress,
                        ReaderSpeechController.MIN_ARTICULATION_SCALE,
                        ReaderSpeechController.MAX_ARTICULATION_SCALE
                    ),
                    voice.selectedItemPosition
                )
            }
            .show()
    }

    private fun slider(
        context: Context,
        label: String,
        value: Float,
        min: Float,
        max: Float,
        valueView: TextView,
        parent: LinearLayout
    ): SeekBar {
        val title = TextView(context).apply {
            text = label
            textSize = 15f
            setPadding(0, 16, 0, 0)
        }
        val seekBar = SeekBar(context).apply {
            this.max = SLIDER_STEPS
            progress = valueToProgress(value, min, max)
            layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        }
        fun render(progress: Int) {
            valueView.text = String.format(
                Locale.getDefault(),
                "%.2f×",
                progressToValue(progress, min, max)
            )
        }
        seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) = render(progress)
            override fun onStartTrackingTouch(seekBar: SeekBar?) = Unit
            override fun onStopTrackingTouch(seekBar: SeekBar?) = Unit
        })
        render(seekBar.progress)
        parent.addView(title)
        parent.addView(valueView)
        parent.addView(seekBar)
        return seekBar
    }

    private fun valueToProgress(value: Float, min: Float, max: Float): Int =
        (((value.coerceIn(min, max) - min) / (max - min)) * SLIDER_STEPS).roundToInt()

    private fun progressToValue(progress: Int, min: Float, max: Float): Float =
        min + (max - min) * progress.coerceIn(0, SLIDER_STEPS) / SLIDER_STEPS

    private const val SLIDER_STEPS = 300
}
