///|
fn product_kind_name(kind : ProductKind) -> String {
  match kind {
    Project => "Project"
    Site => "Site"
    Building => "Building"
    Storey => "Storey"
    Space => "Space"
    Wall => "Wall"
    Door => "Door"
    Window => "Window"
    Beam => "Beam"
    Column => "Column"
    Slab => "Slab"
    Roof => "Roof"
    Stair => "Stair"
    Ramp => "Ramp"
    Opening => "Opening"
    Generic => "Generic"
  }
}

///|
/// Count products by their normalized IFC family name.
pub fn product_kind_counts(products : Array[Product]) -> Map[String, Int] {
  let result : Map[String, Int] = Map([])
  for product in products {
    result.update_or_default(product_kind_name(product.kind), 1, count => {
      count + 1
    })
  }
  result
}

///|
pub fn property_name_counts(
  property_sets : Array[PropertySet],
) -> Map[String, Int] {
  let result : Map[String, Int] = Map([])
  for property_set in property_sets {
    for property in property_set.properties {
      result.update_or_default(property.name, 1, count => count + 1)
    }
  }
  result
}

///|
pub fn total_estimated_volume(
  index : ModelIndex,
  products : Array[Product],
) -> Double {
  products.fold(init=0.0, (total, product) => {
    geometries_for_product(index, product).fold(init=total, (
      geometry_total,
      geometry,
    ) => {
      match estimated_volume(geometry) {
        Some(volume) => geometry_total + volume
        None => geometry_total
      }
    })
  })
}

///|
fn geometry_kind_name(kind : GeometryKind) -> String {
  match kind {
    Extrusion => "Extrusion"
    FacetedBrep => "FacetedBrep"
    TriangulatedMesh => "TriangulatedMesh"
    CsgSolid => "CsgSolid"
    Profile => "Profile"
    Polyline => "Polyline"
    PointCloud => "PointCloud"
    Unknown => "Unknown"
  }
}

///|
/// Count geometry adapters by their stable output kind name.
pub fn geometry_kind_counts(index : ModelIndex) -> Map[String, Int] {
  let result : Map[String, Int] = Map([])
  for entity in geometry_entities(index) {
    let kind = geometry_for_entity(index, entity).kind
    result.update_or_default(geometry_kind_name(kind), 1, count => count + 1)
  }
  result
}