use std::collections::HashMap;
use serde::Serialize;
use crate::enumerations::enum_field_value::NameFilter;
use crate::traits::trait_communs::{BuildFromParent, BuildFromSon, GetValueFieldForSourceParent, GetValueFieldForSourceSecondary, GetValuePKFieldForSourceSecondary, GetValuePropertyOfKeyParent, HasMatchKey};
fn build_filtre_callback(
type_filter: Option<NameFilter>,
filter_by_name: Option<String>,
) -> Box<dyn Fn(&str) -> bool> {
let valeur = filter_by_name.unwrap_or_default();
match type_filter {
Some(NameFilter::Equal) => Box::new(move |nom: &str| {
nom.to_uppercase().eq(valeur.to_uppercase().as_str())
}),
Some(NameFilter::Begin) => Box::new(move |nom: &str| {
nom.to_uppercase().starts_with(valeur.to_uppercase().as_str())
}),
Some(NameFilter::Finished) => Box::new(move |nom: &str| {
nom.to_uppercase().ends_with(valeur.to_uppercase().as_str())
}),
Some(NameFilter::Contains) => Box::new(move |nom: &str| {
nom.to_uppercase().contains(valeur.to_uppercase().as_str())
}),
_ => Box::new(|_: &str| true),
}
}
pub fn get_parents_with_their_childrens<ParentSource,SourceSon,TEnfant,SourceDestination>(
source_parent:Vec<ParentSource>,
source_son:&Vec<SourceSon>,
source_enfants:&Vec<TEnfant>,
type_filter:Option<NameFilter> ,
filter_by_name:Option<String>
)-> Vec<SourceDestination>
where
ParentSource: GetValuePropertyOfKeyParent + GetValueFieldForSourceParent<TEnfant>,
SourceSon: GetValuePKFieldForSourceSecondary + GetValueFieldForSourceSecondary,
TEnfant: BuildFromSon + Serialize + HasMatchKey + Clone + GetValueFieldForSourceSecondary,
SourceDestination: BuildFromParent
{
let is_filtre_passed=build_filtre_callback(type_filter, filter_by_name);
let mut hasmap_indexed__enfants:HashMap<&str,&TEnfant> =HashMap::new();
source_enfants.iter().for_each(|enfant|{
hasmap_indexed__enfants.insert(enfant.get_match_key(), enfant);
});
let mut hasmap_indexed_liaisons:HashMap<&str,Vec<&SourceSon>>=HashMap::new();
source_son.iter().for_each(|liaison|{
hasmap_indexed_liaisons.entry(liaison.get_FK_field_of_source_secondary())
.or_default().push(liaison);
});
source_parent.iter()
.filter(|parent|is_filtre_passed(&parent.get_value()))
.map(|parent| {
let enfants = get_childrens_of_parent(
hasmap_indexed_liaisons.get(parent.get_value()).map(|v| v.as_slice()).unwrap_or(&[]),
&hasmap_indexed__enfants,
);
SourceDestination::build(parent.get_values_of_property(enfants))
})
.collect()
}
pub fn get_childrens_of_parent<TEnfant,TJointure>(
liaison_of_parent:&[&TJointure],
enfants_source:&HashMap<&str,&TEnfant>
) -> Vec<TEnfant>
where
TJointure: GetValuePKFieldForSourceSecondary + GetValueFieldForSourceSecondary,
TEnfant: Clone + HasMatchKey + BuildFromSon + GetValueFieldForSourceSecondary
{
liaison_of_parent.iter()
.filter_map(|row| {
let key_enfant=row.get_field_of_source_secondary();
enfants_source.get(key_enfant).map(|enfant| {
let mut fields_of_enfant_join_liaison=enfant.get_values_of_property();
row.get_values_of_property().iter().for_each(|(key,val)| {
fields_of_enfant_join_liaison.entry(key.to_string()).or_insert(val.clone());
});
TEnfant::build(fields_of_enfant_join_liaison)
})
}).collect()
}