///|
/// A source position measured in Unicode code units.
pub(all) struct SourcePosition {
  offset : Int
  line : Int
  column : Int
} derive(Debug, Eq)

///|
pub fn SourcePosition::new(
  offset~ : Int,
  line~ : Int,
  column~ : Int,
) -> SourcePosition {
  { offset, line, column }
}

///|
/// A value in an IFC STEP entity argument list.
pub(all) enum Value {
  Null
  Omitted
  Integer(Int64)
  Real(Double)
  String(String)
  Enumeration(String)
  Reference(Int)
  Binary(String)
  Typed(name~ : String, value~ : Value)
  List(Array[Value])
} derive(Debug, Eq)

///|
pub fn Value::is_null(self : Value) -> Bool {
  match self {
    Null | Omitted => true
    _ => false
  }
}

///|
pub fn Value::as_reference(self : Value) -> Int? {
  match self {
    Reference(id) => Some(id)
    _ => None
  }
}

///|
pub fn Value::as_string(self : Value) -> String? {
  match self {
    String(value) => Some(value)
    Enumeration(value) => Some(value)
    Binary(value) => Some(value)
    Typed(name~, value~) =>
      match value.as_string() {
        Some(value) => Some(value)
        None => Some(name)
      }
    _ => None
  }
}

///|
pub fn Value::as_int(self : Value) -> Int? {
  match self {
    Integer(value) => Some(value.to_int())
    Real(value) => Some(value.to_int())
    _ => None
  }
}

///|
pub fn Value::as_double(self : Value) -> Double? {
  match self {
    Integer(value) => Some(value.to_double())
    Real(value) => Some(value)
    _ => None
  }
}

///|
/// A raw IFC entity. Unknown entity names and argument values are preserved.
pub(all) struct Entity {
  id : Int
  name : String
  arguments : Array[Value]
} derive(Debug)

///|
pub fn Entity::new(
  id~ : Int,
  name~ : String,
  arguments~ : Array[Value],
) -> Entity {
  { id, name, arguments }
}

///|
pub fn Entity::argument(self : Entity, index : Int) -> Value? {
  self.arguments.get(index)
}

///|
pub(all) struct Header {
  description : Array[String]
  file_name : String?
  time_stamp : String?
  authors : Array[String]
  organizations : Array[String]
  preprocessor_version : String?
  originating_system : String?
  authorization : String?
  schema_identifiers : Array[String]
} derive(Debug)

///|
pub(all) struct Model {
  header : Header
  entities : Array[Entity]
} derive(Debug)

///|
pub fn Model::new(header~ : Header, entities~ : Array[Entity]) -> Model {
  { header, entities }
}

///|
pub fn Model::entity_count(self : Model) -> Int {
  self.entities.length()
}

///|
pub(all) struct ModelSummary {
  schema : String
  entity_count : Int
  product_count : Int
  property_set_count : Int
  geometry_count : Int
  spatial_count : Int
} derive(Debug)

///|
pub(all) enum ProductKind {
  Project
  Site
  Building
  Storey
  Space
  Wall
  Door
  Window
  Beam
  Column
  Slab
  Roof
  Stair
  Ramp
  Opening
  Generic
} derive(Debug, Eq, Hash)

///|
pub(all) struct Product {
  id : Int
  ifc_type : String
  kind : ProductKind
  global_id : String?
  name : String?
  description : String?
  object_type : String?
  placement : Int?
  representation : Int?
  tag : String?
  property_sets : Array[Int]
  container : Int?
} derive(Debug)

///|
pub(all) struct Property {
  name : String
  description : String?
  value : Value
  unit : Int?
} derive(Debug)

///|
pub(all) struct PropertySet {
  id : Int
  name : String?
  description : String?
  properties : Array[Property]
} derive(Debug)

///|
pub(all) struct Point3 {
  x : Double
  y : Double
  z : Double
} derive(Debug)

///|
pub(all) enum GeometryKind {
  Extrusion
  FacetedBrep
  TriangulatedMesh
  CsgSolid
  Profile
  Polyline
  PointCloud
  Unknown
} derive(Debug, Eq, Hash)

///|
pub(all) struct Geometry {
  source_id : Int
  kind : GeometryKind
  points : Array[Point3]
  references : Array[Int]
  depth : Double?
  profile_width : Double?
  profile_height : Double?
  profile_radius : Double?
  face_count : Int
  triangle_count : Int
} derive(Debug)

///|
pub(all) struct SpatialNode {
  id : Int
  ifc_type : String
  name : String?
  children : Array[SpatialNode]
  products : Array[Int]
} derive(Debug)

///|
pub(all) struct Mesh {
  points : Array[Point3]
  triangles : Array[(Int, Int, Int)]
} derive(Debug)

///|
pub(all) enum EntityFilter {
  Name(String)
  Prefix(String)
  ProductOnly
  All
} derive(Debug)

///|
pub(all) enum DiagnosticSeverity {
  Error
  Warning
  Note
} derive(Debug, Eq)

///|
pub(all) struct Diagnostic {
  severity : DiagnosticSeverity
  code : String
  message : String
  entity_id : Int?
} derive(Debug)

///|
pub(all) struct ValidationReport {
  diagnostics : Array[Diagnostic]
  error_count : Int
  warning_count : Int
} derive(Debug)

///|
pub(all) struct Transform3 {
  m00 : Double
  m01 : Double
  m02 : Double
  m10 : Double
  m11 : Double
  m12 : Double
  m20 : Double
  m21 : Double
  m22 : Double
  tx : Double
  ty : Double
  tz : Double
} derive(Debug)

///|
pub(all) struct BoundingBox {
  min : Point3
  max : Point3
  empty : Bool
} derive(Debug)

///|
pub(all) enum UnitKind {
  Length
  Area
  Volume
  Mass
  Time
  PlaneAngle
  UnknownUnit
} derive(Debug, Eq)

///|
pub(all) struct UnitScale {
  kind : UnitKind
  name : String
  prefix : String?
  to_si : Double
} derive(Debug)

///|
pub(all) struct UnitSystem {
  units : Array[UnitScale]
} derive(Debug)

///|
pub(all) struct ProductQuery {
  kind : ProductKind?
  ifc_type : String?
  name_contains : String?
  container : Int?
  has_properties : Bool
} derive(Debug)

///|
pub(all) struct GraphStats {
  entity_count : Int
  reference_count : Int
  distinct_targets : Int
  max_out_degree : Int
  orphan_reference_count : Int
} derive(Debug)

///|
pub(all) struct EntityAttribute {
  index : Int
  value : Value
} derive(Debug)

///|
pub(all) enum ChangeKind {
  Added
  Removed
  Modified
} derive(Debug, Eq)

///|
pub(all) struct ModelChange {
  kind : ChangeKind
  entity_id : Int
  before : Entity?
  after : Entity?
} derive(Debug)

///|
pub(all) struct ModelDiff {
  changes : Array[ModelChange]
  added : Int
  removed : Int
  modified : Int
} derive(Debug)

///|
pub(all) struct StepDocumentStats {
  byte_length : Int
  line_count : Int
  entity_count : Int
  reference_count : Int
  string_count : Int
  comment_count : Int
} derive(Debug)

///|
pub(all) enum SchemaVersion {
  IFC2X3
  IFC4
  IFC4X3
  UnknownSchema(String)
} derive(Debug, Eq)

///|
pub(all) struct CapabilityReport {
  schema : SchemaVersion
  has_products : Bool
  has_spatial_structure : Bool
  has_properties : Bool
  has_geometry : Bool
  has_units : Bool
} derive(Debug)

///|
pub(all) struct ModelMetrics {
  source_length : Int
  entity_count : Int
  product_count : Int
  relationship_count : Int
  geometry_count : Int
  property_count : Int
  spatial_depth : Int
  reference_count : Int
} derive(Debug)

///|
pub(all) enum SearchField {
  EntityType
  EntityText
  ProductName
  ProductGlobalId
  ProductTag
  PropertyName
  PropertyValue
} derive(Debug, Eq)

///|
pub(all) struct SearchHit {
  entity_id : Int
  product_id : Int?
  field : SearchField
  value : String
} derive(Debug)

///|
pub(all) struct ExportBundle {
  headline : String
  json : String
  products_csv : String
  properties_csv : String
  scene_json : String
} derive(Debug)

///|
pub(all) struct ManifestNode {
  product_id : Int
  ifc_type : String
  name : String?
  kind : ProductKind
  property_names : Array[String]
  geometry_count : Int
  bounds : BoundingBox
} derive(Debug)

///|
pub(all) struct RenderManifest {
  schema : String
  nodes : Array[ManifestNode]
  bounds : BoundingBox
} derive(Debug)

///|
pub(all) struct SceneItem {
  product : Product
  geometries : Array[Geometry]
  transform : Transform3
  bounds : BoundingBox
} derive(Debug)

///|
pub(all) struct BimScene {
  items : Array[SceneItem]
  roots : Array[SpatialNode]
  bounds : BoundingBox
} derive(Debug)

///|
pub(all) struct Inspection {
  model : Model
  summary : ModelSummary
  metrics : ModelMetrics
  validation : ValidationReport
  capabilities : CapabilityReport
} derive(Debug)

///|
/// A three-dimensional vector used by mesh and placement analysis.
pub(all) struct Vector3 {
  x : Double
  y : Double
  z : Double
} derive(Debug)

///|
/// Counts and quality signals calculated from a triangle mesh.
pub(all) struct MeshStats {
  point_count : Int
  triangle_count : Int
  boundary_edge_count : Int
  non_manifold_edge_count : Int
  degenerate_triangle_count : Int
  connected_component_count : Int
  surface_area : Double
  signed_volume : Double
} derive(Debug)

///|
/// A mesh together with reusable diagnostics for downstream renderers.
pub(all) struct MeshAnalysis {
  mesh : Mesh
  stats : MeshStats
  bounds : BoundingBox
  normals : Array[Vector3]
} derive(Debug)

///|
/// Spatial roll-up metrics for a subtree or an entire model.
pub(all) struct SpatialMetrics {
  node_count : Int
  leaf_count : Int
  product_count : Int
  max_depth : Int
  occupied_volume : Double
  bounds : BoundingBox
} derive(Debug)

///|
/// A precomputed model view for applications that issue many queries.
pub(all) struct ModelCatalog {
  model : Model
  index : ModelIndex
  products : Array[Product]
  property_sets : Array[PropertySet]
  roots : Array[SpatialNode]
  metrics : ModelMetrics
  type_counts : Map[String, Int]
} derive(Debug)

///|
pub(all) enum CatalogSortKey {
  EntityId
  EntityType
  ProductName
  ProductKind
  PropertyValue
} derive(Debug, Eq)

///|
pub(all) enum SortDirection {
  Ascending
  Descending
} derive(Debug, Eq)

///|
/// A composable query for indexed products.
pub(all) struct CatalogQuery {
  kind : ProductKind?
  ifc_type : String?
  name_contains : String?
  property_contains : String?
  container : Int?
  sort_key : CatalogSortKey
  direction : SortDirection
  offset : Int
  limit : Int
} derive(Debug)

///|
/// A page returned by a catalog query.
pub(all) struct CatalogPage {
  products : Array[Product]
  total_matches : Int
  offset : Int
  limit : Int
  has_next : Bool
} derive(Debug)

///|
pub(all) enum EntityPatch {
  Add(Entity)
  Remove(Int)
  Replace(Entity)
  SetAttribute(id~ : Int, index~ : Int, value~ : Value)
} derive(Debug)

///|
pub(all) struct ModelPatch {
  operations : Array[EntityPatch]
  mut added : Int
  mut removed : Int
  mut replaced : Int
  mut changed_attributes : Int
} derive(Debug)

///|
pub suberror EditError {
  DuplicateEntity(id~ : Int)
  MissingEntity(id~ : Int)
  InvalidAttribute(index~ : Int)
  EmptyPatch
} derive(Debug, Eq)

///|
/// A physical STEP entity record found by the streaming scanner.
pub(all) struct StepRecord {
  id : Int
  name : String
  start_offset : Int
  end_offset : Int
  line : Int
  raw : String
} derive(Debug)

///|
/// Statistics collected without constructing the complete entity graph.
pub(all) struct StreamStats {
  source_length : Int
  record_count : Int
  reference_count : Int
  max_record_length : Int
  comment_count : Int
  line_count : Int
  schema : String?
} derive(Debug)

///|
/// A lightweight schema rule used by the validation layer.
pub(all) struct SchemaRule {
  entity_name : String
  minimum_arguments : Int
  maximum_arguments : Int?
  required_reference_arguments : Array[Int]
  family : String
  description : String
} derive(Debug)

///|
pub(all) struct SchemaProfile {
  name : String
  version : SchemaVersion
  rules : Array[SchemaRule]
  known_entity_count : Int
} derive(Debug)

///|
pub(all) struct SchemaIssue {
  code : String
  entity_id : Int
  entity_name : String
  message : String
  severity : DiagnosticSeverity
} derive(Debug)

///|
pub(all) struct SchemaReport {
  profile : SchemaProfile
  checked_entities : Int
  issues : Array[SchemaIssue]
  error_count : Int
  warning_count : Int
} derive(Debug)

///|
pub(all) enum ExportFormat {
  Obj
  Ply
  JsonLines
  WebBim
} derive(Debug, Eq)

///|
pub(all) struct ExportOptions {
  format : ExportFormat
  include_empty_products : Bool
  include_normals : Bool
  include_properties : Bool
  precision : Int
} derive(Debug)

///|
pub(all) struct ExportedAsset {
  format : ExportFormat
  file_name : String
  content : String
  product_count : Int
  point_count : Int
  triangle_count : Int
} derive(Debug)

///|
/// A single repeatable benchmark measurement.
pub(all) struct BenchmarkCase {
  name : String
  iterations : Int
  source_length : Int
  entity_count : Int
} derive(Debug)

///|
pub(all) struct BenchmarkResult {
  name : String
  iterations : Int
  elapsed_millis : UInt64
  operations_per_second : Double
  source_length : Int
  entity_count : Int
  allocated_entities : Int
} derive(Debug)

///|
pub(all) struct BenchmarkReport {
  toolchain : String
  cases : Array[BenchmarkResult]
  notes : Array[String]
} derive(Debug)

///|
/// Aggregate shape information for a nested STEP value.
pub(all) struct ValueStats {
  node_count : Int
  maximum_depth : Int
  reference_count : Int
  string_count : Int
  number_count : Int
  list_count : Int
  omitted_count : Int
} derive(Debug)

///|
/// Cheap source-level health indicators used before allocating a full model.
pub(all) struct SourceHealth {
  byte_length : Int
  line_count : Int
  record_count : Int
  maximum_record_length : Int
  reference_count : Int
  balanced_parentheses : Bool
  balanced_strings : Bool
  has_iso_header : Bool
  has_end_marker : Bool
} derive(Debug)

///|
pub(all) struct SourceWindow {
  start : Int
  end : Int
  text : String
  line : Int
} derive(Debug)

///|
pub(all) struct EntityRange {
  first_id : Int
  last_id : Int
  entity_count : Int
  contiguous : Bool
} derive(Debug)