use mig_types::segment::OwnedSegment;
use super::EvaluationContext;
pub type Path<'a> = Vec<(&'a str, usize)>;
pub fn sg8s<'a>(ctx: &EvaluationContext<'a>) -> Vec<Path<'a>> {
ctx.scopes_under("SG4", "SG8").unwrap_or_default()
}
pub fn seq_at(ctx: &EvaluationContext, path: &[(&str, usize)]) -> Option<(String, String)> {
ctx.find_segments_at(path, "SEQ").first().map(|s| {
(
s.get_element(0).to_string(),
s.get_component(1, 0).to_string(),
)
})
}
pub fn rffs_at(
ctx: &EvaluationContext,
path: &[(&str, usize)],
qualifier: &str,
) -> Vec<OwnedSegment> {
ctx.find_segments_at(path, "RFF")
.into_iter()
.filter(|s| s.get_element(0) == qualifier)
.collect()
}
pub fn rff_values_at(
ctx: &EvaluationContext,
path: &[(&str, usize)],
qualifier: &str,
) -> Vec<String> {
rffs_at(ctx, path, qualifier)
.iter()
.map(|s| s.get_component(0, 1).to_string())
.filter(|v| !v.is_empty())
.collect()
}
pub fn sg10_at(
ctx: &EvaluationContext,
path: &[(&str, usize)],
pred: impl Fn(&[OwnedSegment]) -> bool,
) -> bool {
ctx.child_segments_at(path, "SG10", &["CCI", "CAV"])
.iter()
.any(|segs| pred(segs))
}
pub fn has_cci(segs: &[OwnedSegment], klassentyp: &str, merkmal: &str) -> bool {
segs.iter().any(|s| {
s.id == "CCI"
&& (klassentyp.is_empty() || s.get_element(0) == klassentyp)
&& s.get_component(2, 0) == merkmal
})
}
pub fn has_cav(segs: &[OwnedSegment], code: &str) -> bool {
segs.iter()
.any(|s| s.id == "CAV" && s.get_element(0) == code)
}
pub fn malo_ids(ctx: &EvaluationContext) -> Vec<String> {
ctx.scopes_under("SG4", "SG5")
.unwrap_or_default()
.iter()
.flat_map(|path| ctx.find_segments_at(path, "LOC"))
.filter(|s| s.get_element(0) == "Z16")
.map(|s| s.get_component(1, 0).to_string())
.filter(|v| !v.is_empty())
.collect()
}
pub fn z01_of_malo_has(
ctx: &EvaluationContext,
refs: &[String],
pred: impl Fn(&[OwnedSegment]) -> bool,
) -> bool {
let malos = malo_ids(ctx);
let refs: Vec<&String> = refs.iter().filter(|r| malos.contains(r)).collect();
if refs.is_empty() {
return false;
}
sg8s(ctx).iter().any(|path| {
seq_at(ctx, path).is_some_and(|(code, _)| code == "Z01")
&& rff_values_at(ctx, path, "Z18")
.iter()
.any(|v| refs.contains(&v))
&& sg10_at(ctx, path, &pred)
})
}
pub fn other_sg8s<'a>(ctx: &EvaluationContext<'a>, own: &[(&str, usize)]) -> Vec<Path<'a>> {
sg8s(ctx)
.into_iter()
.filter(|path| path.as_slice() != own)
.collect()
}
pub fn z02_of_same_malo_has(
ctx: &EvaluationContext,
own: &[(&str, usize)],
obis: impl Fn(&str) -> bool,
) -> bool {
let refs = rff_values_at(ctx, own, "Z18");
!refs.is_empty()
&& other_sg8s(ctx, own).iter().any(|path| {
seq_at(ctx, path).is_some_and(|(code, _)| code == "Z02")
&& rff_values_at(ctx, path, "Z18")
.iter()
.any(|v| refs.contains(v))
&& ctx
.find_segments_at(path, "PIA")
.iter()
.any(|s| s.get_element(0) == "5" && obis(s.get_component(1, 0)))
})
}
pub fn objektcode_elsewhere(
ctx: &EvaluationContext,
own: &[(&str, usize)],
kinds: &[&str],
same_nummer: bool,
same_zeitraum: bool,
) -> bool {
let Some((code, zeitraum)) = seq_at(ctx, own).filter(|(c, _)| kinds.contains(&c.as_str()))
else {
return false;
};
let objektcodes = |path: &[(&str, usize)]| -> Vec<(String, String)> {
rffs_at(ctx, path, "Z33")
.iter()
.map(|s| {
(
s.get_component(0, 1).to_string(),
s.get_component(0, 2).to_string(),
)
})
.filter(|(c, _)| !c.is_empty())
.collect()
};
let mine = objektcodes(own);
!mine.is_empty()
&& other_sg8s(ctx, own).iter().any(|path| {
seq_at(ctx, path).is_some_and(|(c, z)| c == code && (!same_zeitraum || z == zeitraum))
&& objektcodes(path).iter().any(|(c, n)| {
mine.iter()
.any(|(mc, mn)| c == mc && (!same_nummer || n == mn))
})
})
}
pub fn z01_of_zeitraum<'a>(ctx: &EvaluationContext<'a>, own: &[(&str, usize)]) -> Vec<Path<'a>> {
let Some((_, zeitraum)) = seq_at(ctx, own).filter(|(_, z)| !z.is_empty()) else {
return Vec::new();
};
sg8s(ctx)
.into_iter()
.filter(|path| seq_at(ctx, path).is_some_and(|(c, z)| c == "Z01" && z == zeitraum))
.collect()
}
pub fn ruhende_malo_with_zeitraum(ctx: &EvaluationContext, zeitraum: &str) -> bool {
ctx.scopes_under("SG4", "SG5")
.unwrap_or_default()
.iter()
.flat_map(|path| ctx.find_segments_at(path, "LOC"))
.any(|s| s.get_element(0) == "Z22" && s.get_component(1, 3) == zeitraum)
}