package com.onthelevel.core.sensors

import kotlin.math.abs
import kotlin.math.max

/** The one source of truth for Surface bubble placement and screen-relative direction. */
object SurfaceGuidance {
    const val VISUAL_RANGE_DEGREES = 5.0
    const val DIRECTION_DEADBAND_DEGREES = 0.1
    const val CORNER_MINOR_AXIS_RATIO = 0.25
    val RING_DEGREES = listOf(1.0, 2.0, 5.0)

    data class Guidance(
        val normalizedX: Double,
        val normalizedY: Double,
        val highLabel: String?,
    )

    fun from(pitchDegrees: Double, rollDegrees: Double): Guidance {
        val x = visualPosition(rollDegrees)
        val y = -visualPosition(pitchDegrees) // Compose Y grows downward; positive pitch means top is high.
        return Guidance(x, y, highLabel(pitchDegrees, rollDegrees))
    }

    fun ringRadiusRatio(degrees: Double): Double = (degrees / VISUAL_RANGE_DEGREES).coerceIn(0.0, 1.0)

    private fun visualPosition(degrees: Double): Double =
        (degrees / VISUAL_RANGE_DEGREES).coerceIn(-1.0, 1.0)

    private fun highLabel(pitch: Double, roll: Double): String? {
        val pitchMagnitude = abs(pitch)
        val rollMagnitude = abs(roll)
        val dominant = max(pitchMagnitude, rollMagnitude)
        if (dominant < DIRECTION_DEADBAND_DEGREES) return null
        val topOrBottom = if (pitch >= 0.0) "top" else "bottom"
        val leftOrRight = if (roll >= 0.0) "right" else "left"
        val minor = minOf(pitchMagnitude, rollMagnitude)
        return if (minor / dominant < CORNER_MINOR_AXIS_RATIO) {
            if (pitchMagnitude >= rollMagnitude) "High: $topOrBottom edge" else "High: $leftOrRight edge"
        } else {
            "High: $topOrBottom-$leftOrRight"
        }
    }
}
