1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use teo_parser::ast::schema::Schema;
use teo_parser::r#type::Type;
use teo_parser::traits::named_identifiable::NamedIdentifiable;
use teo_parser::traits::resolved::Resolve;
use teo_result::Result;
use teo_teon::types::enum_variant::EnumVariant;
use teo_teon::{teon, Value};
use crate::data_set::{DataSet, Group, Record};
use crate::namespace::Namespace;
use crate::schema::fetch::fetchers::fetch_literals::fetch_dictionary_literal;
use crate::traits::named::Named;

pub fn load_data_sets(namespace: &Namespace, names: Option<&Vec<String>>, all: bool, schema: &Schema) -> Result<Vec<DataSet>> {
    let mut result: Vec<DataSet> = vec![];
    for schema_data_set in schema.data_sets() {
        if all || (names.is_some() && names.unwrap().contains(&schema_data_set.string_path().join("."))) || (names.is_none() && schema_data_set.auto_seed) {
            if result.iter().find(|d| &d.name == schema_data_set.string_path()).is_none() {
                result.push(DataSet {
                    notrack: false,
                    autoseed: false,
                    name: schema_data_set.string_path().clone(),
                    groups: vec![]
                });
            }
            let data_set = result.iter_mut().find(|d| &d.name == schema_data_set.string_path()).unwrap();
            data_set.notrack = schema_data_set.notrack;
            data_set.autoseed = schema_data_set.auto_seed;
            for schema_group in schema_data_set.groups() {
                if data_set.groups.iter().find(|g| &g.name == schema_group.resolved().string_path()).is_none() {
                    data_set.groups.push(Group {
                        name: schema_group.resolved().string_path().clone(),
                        records: vec![]
                    });
                }
                let group = data_set.groups.iter_mut().find(|g| &g.name == schema_group.resolved().string_path()).unwrap();
                for schema_record in schema_group.records() {
                    let record = Record {
                        name: schema_record.identifier().name().to_owned(),
                        value: fetch_dictionary_literal(schema_record.dictionary(), schema, schema_record, &Type::Undetermined, namespace)?.as_teon().unwrap().clone(),
                    };
                    group.records.push(record);
                }
            }
            normalize_dataset_relations(data_set, namespace);
        }
    }
    Ok(result)
}

pub(crate) fn normalize_dataset_relations<'a>(dataset: &mut DataSet, namespace: &Namespace) {
    let mut assign_relation_other_sides = vec![];
    for group in &dataset.groups {
        let model = namespace.model_at_path(&group.model_path()).unwrap();
        for record in &group.records {
            for (k, v) in record.value.as_dictionary().unwrap() {
                if let Some(relation) = model.relation(k) {
                    let (opposite_model, opposite_rel) = namespace.opposite_relation(relation);
                    // If there isn't a relation defined on the opposite side, just leave it here
                    if opposite_rel.is_none() {
                        continue
                    }
                    let opposite_rel = opposite_rel.unwrap();
                    if relation.is_vec {
                        for v in v.as_array().unwrap() {
                            assign_relation_other_sides.push((dataset.name.clone(), opposite_model.path.clone(), v.as_enum_variant().unwrap().value.as_str().to_owned(), opposite_rel.name.clone(), record.name.clone()));
                        }
                    } else {
                        assign_relation_other_sides.push((dataset.name.clone(), opposite_model.path.clone(), v.as_enum_variant().unwrap().value.as_str().to_owned(), opposite_rel.name.clone(), record.name.clone()));
                    }
                }
            }
        }
    }
    for (data_set_name, model_name, record_name, field_name, value_name) in &assign_relation_other_sides {
        assign_relation_other_side(dataset, data_set_name, model_name, record_name, field_name, value_name, namespace);
    }
}

fn assign_relation_other_side(dataset: &mut DataSet, data_set_name: &Vec<String>, model_name: &Vec<String>, record_name: &String, field_name: &String, value_name: &String, namespace: &Namespace) {
    let that_group = dataset.groups.iter_mut().find(|g| &g.name == model_name).unwrap();
    let that_record = that_group.records.iter_mut().find(|r| &r.name == record_name).unwrap();
    let model = namespace.model_at_path(&model_name.iter().map(AsRef::as_ref).collect()).unwrap();
    let relation = model.relation(field_name).unwrap();
    if relation.is_vec {
        if that_record.value.as_dictionary_mut().unwrap().contains_key(relation.name()) {
            let array = that_record.value.as_dictionary_mut().unwrap().get_mut(relation.name()).unwrap().as_array_mut().unwrap();
            let to_insert = Value::EnumVariant(EnumVariant {
                value: value_name.clone(),
                args: None,
            });
            if !array.contains(&to_insert) {
                array.push(to_insert);
            }
        } else {
            that_record.value.as_dictionary_mut().unwrap().insert(relation.name().to_owned(), teon!([Value::EnumVariant(EnumVariant {
                value: value_name.clone(),
                args: None,
            })]));
        }
    } else {
        that_record.value.as_dictionary_mut().unwrap().insert(relation.name().to_owned(), Value::EnumVariant(EnumVariant {
            value: value_name.clone(),
            args: None,
        }));
    }
}