use ifc_model::guid::Guid;
use ifc_model::{Entity, EntityId, Model, Transaction, Value};
use super::owned_relationships::{pair_owned, refs};
use crate::authoring::{invalid, SpatialAuthoringResult};
use crate::relation::slots::{
RelSlots, CONNECTS_ELEMENTS, CONNECTS_WITH_REALIZING, INTERFERES_ELEMENTS,
};
pub(super) fn check_realizing(realizing: &[EntityId]) -> SpatialAuthoringResult<()> {
if realizing.is_empty() {
return Err(invalid(
CONNECTS_WITH_REALIZING.type_name,
"RealizingElements",
"empty",
));
}
Ok(())
}
pub(super) fn distinct(
rel: RelSlots,
global_id: &str,
relating: EntityId,
related: EntityId,
) -> SpatialAuthoringResult<()> {
if Guid::parse(global_id).is_none() {
return Err(invalid(rel.type_name, "GlobalId", global_id));
}
if relating == related {
return Err(invalid(
rel.type_name,
"RelatedElement",
"an element cannot connect to itself",
));
}
Ok(())
}
fn pair(
tx: &mut Transaction,
rel: RelSlots,
global_id: &str,
relating: EntityId,
related: EntityId,
width: usize,
) -> SpatialAuthoringResult<EntityId> {
distinct(rel, global_id, relating, related)?;
let mut attributes = vec![Value::Null; width];
attributes[0] = Value::Text(global_id.into());
attributes[rel.relating] = Value::Ref(relating);
attributes[rel.related] = Value::Ref(related);
Ok(tx.create(Entity::new(rel.type_name, attributes)))
}
pub fn connect_elements(
tx: &mut Transaction,
global_id: &str,
relating: EntityId,
related: EntityId,
) -> SpatialAuthoringResult<EntityId> {
pair(tx, CONNECTS_ELEMENTS, global_id, relating, related, 7)
}
pub fn connect_with_realizing_elements(
tx: &mut Transaction,
model: &Model,
global_id: &str,
relating: EntityId,
related: EntityId,
realizing: &[EntityId],
) -> SpatialAuthoringResult<EntityId> {
check_realizing(realizing)?;
pair_owned(
tx,
model,
CONNECTS_WITH_REALIZING,
global_id,
relating,
related,
vec![("RealizingElements", refs(realizing))],
None,
)
}
pub fn interfere_elements(
tx: &mut Transaction,
model: &Model,
global_id: &str,
relating: EntityId,
related: EntityId,
implied_order: Option<bool>,
) -> SpatialAuthoringResult<EntityId> {
pair_owned(
tx,
model,
INTERFERES_ELEMENTS,
global_id,
relating,
related,
vec![(
"ImpliedOrder",
implied_order.map_or(Value::LogicalUnknown, Value::Bool),
)],
None,
)
}