use std::{fs, io, path::Path};

pub struct MatrixMeta {
    pub n: usize,
    pub n_cols: usize,
}

impl MatrixMeta {
    pub fn load(dir: &Path) -> io::Result<Self> {
        let s = fs::read_to_string(dir.join("meta.json"))?;
        parse(&s).ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "bad meta.json"))
    }

    pub fn save(&self, dir: &Path) -> io::Result<()> {
        fs::write(
            dir.join("meta.json"),
            format!("{{\"n\":{},\"n_cols\":{}}}\n", self.n, self.n_cols),
        )
    }
}

fn parse(s: &str) -> Option<MatrixMeta> {
    Some(MatrixMeta { n: field(s, "n")?, n_cols: field(s, "n_cols")? })
}

pub(crate) fn field(s: &str, name: &str) -> Option<usize> {
    let key = format!("\"{}\":", name);
    let pos = s.find(&key)? + key.len();
    let rest = s[pos..].trim_start();
    let end = rest.find(|c: char| !c.is_ascii_digit()).unwrap_or(rest.len());
    rest[..end].parse().ok()
}
