use ifc_lite_core::{DecodedEntity, EntityDecoder, IfcType};
use std::collections::HashMap;
use super::color::resolve_color_via_styles;
use super::primitives::{SymbolicData, SymbolicText};
use super::transform::{compose_transforms, parse_axis2_placement_2d, Transform2D};
#[allow(clippy::too_many_arguments)]
pub(super) fn extract_text_literal(
item: &DecodedEntity,
decoder: &mut EntityDecoder,
express_id: u32,
ifc_type: &str,
rep_identifier: &str,
unit_scale: f32,
transform: &Transform2D,
rtc_x: f32,
rtc_z: f32,
styled_items: &HashMap<u32, Vec<u32>>,
out: &mut SymbolicData,
) {
let content = match item.get(0).and_then(|a| a.as_string()) {
Some(s) => s.to_string(),
None => return,
};
let placement_transform = match item.get_ref(1) {
Some(p_ref) => match decoder.decode_by_id(p_ref) {
Ok(p) => parse_axis2_placement_2d(&p, decoder, unit_scale),
Err(_) => Transform2D::unresolved(), },
None => Transform2D::unresolved(), };
let composed = compose_transforms(transform, &placement_transform);
const CAP_TO_BOX_RATIO: f32 = 0.7;
const FALLBACK_CAP_HEIGHT_M: f32 = 0.18;
let height_model_units = if item.ifc_type == IfcType::IfcTextLiteralWithExtent {
item.get_ref(3)
.and_then(|extent_ref| decoder.decode_by_id(extent_ref).ok())
.and_then(|extent| extent.get(1).and_then(|a| a.as_float()))
.map(|h| (h as f32) * CAP_TO_BOX_RATIO)
.unwrap_or(FALLBACK_CAP_HEIGHT_M / unit_scale.max(1e-6))
} else {
FALLBACK_CAP_HEIGHT_M / unit_scale.max(1e-6)
};
let alignment = if item.ifc_type == IfcType::IfcTextLiteralWithExtent {
item.get(4)
.and_then(|a| a.as_string())
.unwrap_or("")
.to_string()
} else {
String::new()
};
let (wx, wy) = composed.transform_point(0.0, 0.0);
let raw_scale = composed.scale();
let text_scale = if raw_scale.is_finite() { raw_scale } else { 1.0 };
let dir = if raw_scale.is_finite() && raw_scale > 0.0 {
(composed.m00 / raw_scale, -composed.m10 / raw_scale)
} else {
(1.0, 0.0)
};
let color = resolve_color_via_styles(item.id, styled_items, decoder)
.unwrap_or([0.05, 0.05, 0.05, 1.0]);
out.texts.push(SymbolicText {
express_id,
ifc_type: ifc_type.to_string(),
x: wx - rtc_x,
y: -wy + rtc_z,
dir_x: dir.0,
dir_y: dir.1,
height: height_model_units * unit_scale * text_scale,
content,
alignment,
world_y: composed.tz,
color,
target_px: 0.0,
representation: rep_identifier.to_string(),
});
}