package dev.adriankuta.visualizer

import androidx.compose.ui.graphics.Color
import kotlin.math.sqrt

/**
 * Represents a color in HSL (Hue, Saturation, Lightness) color space.
 * 
 * @param hue The hue component (0-360 degrees)
 * @param saturation The saturation component (0-1)
 * @param lightness The lightness component (0-1)
 */
data class HSL(
    val hue: Float,
    val saturation: Float,
    val lightness: Float
) {
    /**
     * Converts HSL color to RGB values.
     * 
     * @return Triple containing RGB values (0-255)
     */
    fun toRgb(): Triple<Int, Int, Int> {
        val (r, g, b) = hlsToRgb(hue / 360f, lightness, saturation)
        return Triple((r * 255).toInt(), (g * 255).toInt(), (b * 255).toInt())
    }
    
    /**
     * Converts HSL color to Compose Color.
     * 
     * @return Compose Color object
     */
    fun toComposeColor(): Color {
        val (r, g, b) = toRgb()
        return Color(r, g, b)
    }
    
    /**
     * Creates a new HSL color with modified lightness.
     * 
     * @param newLightness The new lightness value (0-1)
     * @return New HSL color with updated lightness
     */
    fun withLightness(newLightness: Float): HSL = copy(lightness = newLightness.coerceIn(0f, 1f))
    
    private fun hlsToRgb(h: Float, l: Float, s: Float): Triple<Float, Float, Float> {
        val r: Float
        val g: Float
        val b: Float

        if (s == 0f) {
            // Achromatic (gray)
            r = l
            g = l
            b = l
        } else {
            val q = if (l < 0.5f) l * (1f + s) else l + s - l * s
            val p = 2f * l - q

            r = hueToRgb(p, q, h + 1f / 3f)
            g = hueToRgb(p, q, h)
            b = hueToRgb(p, q, h - 1f / 3f)
        }

        return Triple(r, g, b)
    }

    private fun hueToRgb(p: Float, q: Float, t: Float): Float {
        var tTemp = t
        if (tTemp < 0f) tTemp += 1f
        if (tTemp > 1f) tTemp -= 1f
        return when {
            tTemp < 1f / 6f -> p + (q - p) * 6f * tTemp
            tTemp < 1f / 2f -> q
            tTemp < 2f / 3f -> p + (q - p) * (2f / 3f - tTemp) * 6f
            else -> p
        }
    }
}

/**
 * Calculates the Root Mean Square (RMS) value of audio data.
 * 
 * @param bytes Audio data as byte array
 * @return RMS value as Double
 */
fun calculateRms(bytes: ByteArray): Double {
    if (bytes.isEmpty()) return 0.0
    var sum = 0.0
    for (b in bytes) {
        val centered = (b.toInt() and 0xFF) - 128
        sum += centered * centered
    }
    return sqrt(sum / bytes.size)
}