use std::collections::HashMap;

// this implementation merges the header and the sections
pub fn parse<'a>(s: &'a str, trtab: &HashMap<&'a str, &'a str>) -> HashMap<&'a str, Vec<&'a str>> {
    let mut ret = HashMap::new();
    let mut it = s.lines().peekable();

    // parse header
    // KEY: VALUE
    while let Some(x) = it.peek() {
        if !x.trim().is_empty() {
            if x.starts_with('%') {
                break;
            }
            if let Some(p) = x.find(':') {
                if p != 0 {
                    ret.insert(&x[..p], vec![x[p + 1..].trim_start()]);
                }
            }
            // else: regard it as comment
        }
        it.next();
    }

    // parse sections
    // %KEY\nVALUE...
    let mut section = None;
    for i in it {
        if let Some(j) = i.strip_prefix('%') {
            if let Some((key, value)) = section.take() {
                ret.insert(key, value);
            }
            section = Some((j.trim_end(), Vec::new()));
        } else if let Some((_, value)) = &mut section {
            value.push(i);
        } else {
            unreachable!();
        }
    }
    if let Some((key, value)) = section {
        ret.insert(key, value);
    }

    // perform translation substitution, e.g. cleanup keys
    for (from, to) in trtab {
        if ret.contains_key(to) {
            // don't do conflict handling for now
            continue;
        }
        if let Some(x) = ret.remove(from) {
            // move element
            ret.insert(to, x);
        }
    }

    // cleanup values
    ret.values_mut().for_each(|val| {
        while let Some(x) = val.pop() {
            if !x.trim().is_empty() {
                val.push(x);
                break;
            }
        }
    });

    ret
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn ex0() {
        let mut trtab = HashMap::new();
        trtab.insert("Kategorie", "Category");
        trtab.insert("Zutaten", "Ingredients");
        trtab.insert("Zubereitung", "Making");
        trtab.insert("Bemerkungen", "Remarks");
        trtab.insert("Quellen", "Sources");

        let mut res = HashMap::new();
        res.insert("Name", vec!["Fränkische Kohlsuppe"]);
        res.insert("Kategorie", vec!["Nullprodukt"]);
        res.insert("Category", vec!["nully..."]);
        res.insert("Ingredients", vec!["Salz"]);
        res.insert("Making", vec!["Mit Wasser abschmecken", " - oder so... "]);
        res.insert("Remarks", vec!["was soll das?"]);
        res.insert("Sources", vec!["keine"]);

        assert_eq!(
            parse(
                r#"
Name: Fränkische Kohlsuppe
Kategorie: Nullprodukt
  Das ist nur ein Kommentar, kein Doppelpunkt...
: Das auch: ...
Category: nully...

%Zutaten
Salz

%Zubereitung
Mit Wasser abschmecken
 - oder so... 

%Bemerkungen
was soll das?

%Quellen
keine


"#,
                &trtab
            ),
            res
        );
    }
}