// Ported from topojson-client v3.1.0 src/bbox.js, ISC.

///|
fn extend_box(box : Array[Double], p : Array[Double]) -> Unit {
  box[0] = box[0].min(p[0])
  box[1] = box[1].min(p[1])
  box[2] = box[2].max(p[0])
  box[3] = box[3].max(p[1])
}

///|
fn Topology::point_bounds(
  self : Topology,
  g : Json,
  box : Array[Double],
) -> Unit {
  match kind(g) {
    "Point" => extend_box(box, self.point(field(g, "coordinates")))
    "MultiPoint" =>
      for p in array(field(g, "coordinates")) {
        extend_box(box, self.point(p))
      }
    "GeometryCollection" =>
      for c in array(field(g, "geometries")) {
        self.point_bounds(c, box)
      }
    _ => ()
  }
}

///|
/// Bounds include all stored arcs, including unreferenced arcs, as in the upstream client.
/// None denotes a completely empty topology.
pub fn Topology::bbox(self : Topology) -> Array[Double]? raise TopoError {
  let box = [1.0 / 0.0, 1.0 / 0.0, -1.0 / 0.0, -1.0 / 0.0]
  for i = 0; i < array(field(self.data, "arcs")).length(); i = i + 1 {
    for p in self.arc(i) {
      extend_box(box, p)
    }
  }
  for name in self.names() {
    self.point_bounds(self.lookup(name), box)
  }
  if box[0].is_inf() {
    None
  } else {
    Some(box)
  }
}