// Radial gauge (speedometer): a value shown as a needle over a colored arc.

///|
/// SVG arc path from angle `a0` to `a1` (radians) along a circle of radius
/// `r` centered at `(cx, cy)`.
fn gauge_arc(
  cx : Double,
  cy : Double,
  r : Double,
  a0 : Double,
  a1 : Double,
) -> String {
  let x0 = cx + r * @math.cos(a0)
  let y0 = cy + r * @math.sin(a0)
  let x1 = cx + r * @math.cos(a1)
  let y1 = cy + r * @math.sin(a1)
  let large = if a1 - a0 > @math.PI { "1" } else { "0" }
  "M " +
  num(x0) +
  " " +
  num(y0) +
  " A " +
  num(r) +
  " " +
  num(r) +
  " 0 " +
  large +
  " 1 " +
  num(x1) +
  " " +
  num(y1)
}

///|
/// Render a radial gauge as a standalone SVG document string. The needle
/// points to `value` on a 180° arc spanning `min`..`max`; the arc is split
/// into colored zones by `bands` (each a fraction in `0..1` of the sweep,
/// cycling the palette). `title`, `width`, `height` and `theme` are optional.
pub fn gauge_chart(
  value : Double,
  min? : Double = 0.0,
  max? : Double = 100.0,
  bands? : Array[Double] = [],
  title? : String = "",
  width? : Double = 320.0,
  height? : Double = 220.0,
  theme? : Theme = Theme::light(),
) -> String {
  let cx = width / 2.0
  let cy = height - 42.0
  let r = {
    let by_w = width / 2.0 - 24.0
    let by_h = height - 70.0
    if by_w < by_h {
      by_w
    } else {
      by_h
    }
  }
  // The gauge sweeps the top half, from 180° (left) to 360° (right).
  let start = @math.PI
  let sweep = @math.PI
  let span = if max > min { max - min } else { 1.0 }
  let frac = {
    let f = (value - min) / span
    if f < 0.0 {
      0.0
    } else if f > 1.0 {
      1.0
    } else {
      f
    }
  }
  let body = StringBuilder::new()
  body.write_string(background_rect(theme, width, height))
  // Colored zones, or a single neutral track when no bands are given.
  if bands.length() == 0 {
    body.write_string(
      elem("path", [
        ("d", gauge_arc(cx, cy, r, start, start + sweep)),
        ("fill", "none"),
        ("stroke", theme.grid),
        ("stroke-width", "14"),
        ("stroke-linecap", "round"),
      ]),
    )
  } else {
    let mut acc = 0.0
    for i in 0..