package com.erwan.revwatch.model.face

/**
 * Complete definition of a custom gauge face.
 * All coordinates/sizes in percentage (0–100) relative to the gauge bounds.
 * Angles in degrees; 0° = 3 o'clock, positive = clockwise.
 */
data class FaceDef(
    val name: String = "Custom",
    val author: String = "",
    val bg: String = "#000000",
    val vars: Map<String, String> = emptyMap(),
    val elements: List<FaceNode> = emptyList()
)

/**
 * A node in the face definition tree.
 * Either a drawable element or a conditional group.
 */
sealed class FaceNode {
    /**
     * A single drawable primitive.
     * @param type  Primitive name (circle, arc, needle, etc.)
     * @param args  Positional arguments (meaning depends on type)
     * @param props Key-value optional properties
     */
    data class Element(
        val type: String,
        val args: List<String>,
        val props: Map<String, String>
    ) : FaceNode()

    /**
     * Conditional block: children are drawn only if the condition evaluates to true.
     * Condition syntax: "$zone==danger", "$progress>0.8", etc.
     */
    data class Conditional(
        val condition: String,
        val children: List<FaceNode>
    ) : FaceNode()

    /**
     * Structural group of elements (no condition).
     * Used for organizational purposes in the editor.
     */
    data class Group(
        val name: String,
        val children: List<FaceNode>
    ) : FaceNode()

    /**
     * For loop: children are drawn repeatedly with $varName iterating from..to.
     */
    data class ForLoop(
        val varName: String,
        val from: String,
        val to: String,
        val step: String = "1",
        val children: List<FaceNode>
    ) : FaceNode()
}

/**
 * Runtime context passed to the renderer with the current gauge state.
 * Mutable to allow reuse without allocation in the render loop.
 */
class FaceRenderContext(
    var progress: Float = 0f,
    var rawValue: Double? = null,
    var formattedValue: String = "--",
    var unit: String = "",
    var label: String = "",
    var minValue: Double = 0.0,
    var maxValue: Double = 100.0,
    var accentColor: Int = 0xFF4FC3F7.toInt(),
    var zone: Zone = Zone.NORMAL,
    var warnLowProgress: Float? = null,
    var warnHighProgress: Float? = null,
    var dangerLowProgress: Float? = null,
    var dangerHighProgress: Float? = null,
    /** Extra variables injected by multi-value data bindings (e.g. $value-oil-temp). */
    var extraVars: Map<String, String> = emptyMap()
) {
    enum class Zone { NORMAL, WARNING, DANGER }

    fun set(
        progress: Float, rawValue: Double?, formattedValue: String,
        unit: String, label: String, minValue: Double, maxValue: Double,
        accentColor: Int, zone: Zone,
        warnLowProgress: Float?, warnHighProgress: Float?,
        dangerLowProgress: Float?, dangerHighProgress: Float?,
        extraVars: Map<String, String> = emptyMap()
    ) {
        this.progress = progress; this.rawValue = rawValue
        this.formattedValue = formattedValue; this.unit = unit; this.label = label
        this.minValue = minValue; this.maxValue = maxValue
        this.accentColor = accentColor; this.zone = zone
        this.warnLowProgress = warnLowProgress; this.warnHighProgress = warnHighProgress
        this.dangerLowProgress = dangerLowProgress; this.dangerHighProgress = dangerHighProgress
        this.extraVars = extraVars
    }
}
