///|
fn time_value(x : @s.Instant?) -> Json {
  match x {
    Some(t) => t.unix_ms().to_json()
    None => (None : Double?).to_json()
  }
}

///|
fn state_value(x : @s.HorizonState) -> Int {
  match x {
    Crosses => 0
    AlwaysAbove => 1
    AlwaysBelow => -1
  }
}

///|
fn main {
  // Same integer day offsets and sites as differential.mjs, no PRNG/runtime dates.
  let days = [
    -25567, -18263, -10593, -3288, 0, 10957, 16188, 19814, 19895, 20078, 29385, 66108,
  ]
  let sites = [
    (-90.0, 0.0),
    (-78.0, -180.0),
    (-66.56, 15.0),
    (-33.86, 151.21),
    (-23.55, -46.63),
    (0.0, 0.0),
    (0.0, 180.0),
    (23.44, -90.0),
    (31.23, 121.47),
    (40.71, -74.0),
    (51.5, 0.0),
    (66.56, 25.0),
    (78.2232, 15.6469),
    (89.999, -180.0),
    (90.0, 0.0),
  ]
  for day in days {
    for hour in [0.0, 6.0, 12.0, 23.0] {
      let ms = day.to_double() * 86400000.0 + hour * 3600000.0
      let date = @s.instant(ms).unwrap()
      for pair in sites {
        let site = @s.observer(pair.0, pair.1).unwrap()
        let sp = @s.sun_position(date, site)
        let mp = @s.moon_position(date, site)
        let il = @s.moon_illumination(date)
        let st = @s.sun_times(date, site)
        let mt = @s.moon_times(date, site)
        let values : Array[Json] = [
          sp.azimuth.to_json(),
          sp.altitude.to_json(),
          mp.azimuth.to_json(),
          mp.altitude.to_json(),
          mp.distance.to_json(),
          mp.parallactic_angle.to_json(),
          il.fraction.to_json(),
          il.phase.to_json(),
          il.angle.to_json(),
          il.waxing.to_json(),
          st.solar_noon.unix_ms().to_json(),
          st.nadir.unix_ms().to_json(),
          state_value(st.state).to_json(),
        ]
        for e in st.events {
          values.push(time_value(e.rise))
          values.push(time_value(e.set))
        }
        values.push(time_value(mt.rise))
        values.push(time_value(mt.set))
        values.push(state_value(mt.state).to_json())
        let cfg = @s.solar_config(100.0, [
          @s.solar_angle(-4.0, "blueStart", "blueEnd").unwrap(),
        ]).unwrap()
        let custom = @s.sun_times_with(date, site, cfg)
        values.push(time_value(custom.event("sunrise")))
        values.push(time_value(custom.event("sunset")))
        values.push(time_value(custom.event("blueStart")))
        values.push(time_value(custom.event("blueEnd")))
        println(values.to_json().stringify())
      }
    }
  }
}