use bevy::prelude::Color;
use serde::Deserialize;
use toml::Table;

#[derive(Deserialize, Debug)]
enum Val {
    A(String),
    B(usize),
    C(bool),
}

fn main() {
    let s = r#"
    [color]
    asdf = true
    [color.foo]
    qwert = false
    [color.foo.bar]
    hjkl = [1,2,3]
    [color.foo.bar.baz]
    Rgba = { red = 1.0, blue = 1.0, green = 1.0, alpha = 1.0 }
    "#;
    let vt = toml::from_str::<Table>(s).unwrap();

    iter_all(&vt, "")
        .iter()
        .for_each(|(k, v)| println!("k {:?} :: v {:?}", k, v));

    let x = get::<Color>(&vt, "color_foo_bar_baz").unwrap();
    println!("{:?}", x);

    let y = get::<Vec<usize>>(&vt, "color_foo_bar_hjkl").unwrap();
    println!("{:?}", y);

    let z = get::<bool>(&vt, "color_foo_qwert").unwrap();
    println!("{:?}", z);
}

fn iter_all(t: &toml::Table, key: &str) -> Vec<(String, toml::Value)> {
    t.iter()
        .flat_map(|(k, v)| {
            let nk = if key == "" {
                k.to_string()
            } else {
                format!("{}_{}", key, k)
            };
            match v {
                toml::Value::Table(nt) => iter_all(nt, nk.as_str()),
                _ => vec![(nk, v.clone())],
            }
        })
        .collect()
}

fn locate(t: &toml::Table, key: &str) -> Option<toml::Value> {
    t.iter().find_map(|(k, v)| {
        if key == k {
            Some(v.clone())
        } else if key.starts_with(k) {
            let prefix = format!("{}_", k);
            match v {
                toml::Value::Table(nt) => locate(nt, key.strip_prefix(prefix.as_str()).unwrap()),
                _ => Some(v.clone()),
            }
        } else {
            None
        }
    })
}

fn get<'de, T: Deserialize<'de>>(t: &toml::Table, key: &str) -> Option<T> {
    locate(t, key).map(|val| val.try_into().ok()).flatten()
}
