///|
pub(all) struct Statistics {
  objects : Int
  geometries : Int
  arcs : Int
  stored_positions : Int
  arc_references : Int
  shared_arcs : Int
  orphan_arcs : Int
  quantized : Bool
} derive(Eq, Debug, ToJson)

///|
/// Count storage and shared ownership. GeometryCollection containers are excluded from geometries.
pub fn Topology::statistics(self : Topology) -> Statistics raise TopoError {
  let arcs = array(field(self.data, "arcs"))
  let leaves = []
  for name in self.names() {
    collect_leaves(self.lookup(name), leaves)
  }
  let owners : Map[Int, Array[Int]] = Map([])
  let mut references = 0
  for k = 0; k < leaves.length(); k = k + 1 {
    for r in geometry_refs(leaves[k]) {
      references += 1
      let id = arc_id(r)
      let a = owners.get(id).unwrap_or([])
      if !a.contains(k) {
        a.push(k)
      }
      owners[id] = a
    }
  }
  let mut positions = 0
  for a in arcs {
    positions += array(a).length()
  }
  let mut shared = 0
  for _, o in owners {
    if o.length() > 1 {
      shared += 1
    }
  }
  {
    objects: self.names().length(),
    geometries: leaves.length(),
    arcs: arcs.length(),
    stored_positions: positions,
    arc_references: references,
    shared_arcs: shared,
    orphan_arcs: arcs.length() - owners.length(),
    quantized: field(self.data, "transform") != Json::null(),
  }
}