#![allow(non_snake_case)]
use std::{fs, io::Write};
#[macro_use]
extern crate scan_fmt;
use csv::Writer;
use serde::Serialize;

#[derive(Serialize)]
struct Properties {
    part_number: String,
    part_name: String,
    material_name: String,
    mass: f64,
    volume: f64,
    density: f64,
    area: f64,
    cmX: f64,
    cmY: f64,
    cmZ: f64,
    bb_length: f64,
    bb_width: f64,
    bb_height: f64,
    Ixx: f64,
    Ixy: f64,
    Ixz: f64,
    Iyx: f64,
    Iyy: f64,
    Iyz: f64,
    Izx: f64,
    Izy: f64,
    Izz: f64,
}

fn main() {
    let mut wtr = Writer::from_writer(vec![]);

    for fpath in fs::read_dir("../parts").unwrap() {
        let infile = fs::read_to_string(fpath.unwrap().path())
            .expect("Cannot read file.")
            .split('\n')
            .map(|l| l.to_owned())
            .collect::<Vec<String>>();

        wtr.serialize(parse_props(infile)).unwrap();
    }

    let data = String::from_utf8(wtr.into_inner().unwrap()).unwrap();

    println!("{}", data);

    let mut outfile = fs::File::create("../compiled.csv").unwrap();

    outfile.write(data.as_bytes()).unwrap();
}

fn parse_props(infile: Vec<String>) -> Properties {
    let part_number = scan_fmt!(&infile[1], "Part Number {/.+/}", String).unwrap();
    let part_name = scan_fmt!(&infile[2], "Part Name {/.+/}", String).unwrap();
    let material_name = scan_fmt!(&infile[4], "Material Name	{/.+/}", String).unwrap();

    let mass = scan_fmt!(&infile[14], "Mass	{} g", f64).unwrap();
    let volume = scan_fmt!(&infile[15], "Volume	{} mm^3", f64).unwrap();
    let density = scan_fmt!(&infile[16], "Density {} g / mm^3", f64).unwrap();
    let area = scan_fmt!(&infile[17], "Area	{} mm^2", f64).unwrap();

    // Center of Mass
    let (cmX, cmY, cmZ) = scan_fmt!(
        &infile[19],
        "Center of Mass	{} mm, {} mm, {} mm",
        f64,
        f64,
        f64
    )
    .unwrap();

    // Bounding Box
    let bb_length = scan_fmt!(&infile[21], "Length {}", f64).unwrap();
    let bb_width = scan_fmt!(&infile[22], "Width {}", f64).unwrap();
    let bb_height = scan_fmt!(&infile[23], "Height {}", f64).unwrap();

    // Moments of Inertia at Center of Mass
    let Ixx = scan_fmt!(&infile[25], "Ixx {}", f64).unwrap();
    let Ixy = scan_fmt!(&infile[26], "Ixy {}", f64).unwrap();
    let Ixz = scan_fmt!(&infile[27], "Ixz {}", f64).unwrap();
    let Iyx = scan_fmt!(&infile[28], "Iyx {}", f64).unwrap();
    let Iyy = scan_fmt!(&infile[29], "Iyy {}", f64).unwrap();
    let Iyz = scan_fmt!(&infile[30], "Iyz {}", f64).unwrap();
    let Izx = scan_fmt!(&infile[31], "Izx {}", f64).unwrap();
    let Izy = scan_fmt!(&infile[32], "Izy {}", f64).unwrap();
    let Izz = scan_fmt!(&infile[33], "Izz {}", f64).unwrap();

    return Properties {
        part_number,
        part_name,
        material_name,
        mass,
        volume,
        density,
        area,
        cmX,
        cmY,
        cmZ,
        bb_length,
        bb_width,
        bb_height,
        Ixx,
        Ixy,
        Ixz,
        Iyx,
        Iyy,
        Iyz,
        Izx,
        Izy,
        Izz,
    };
}
