use std::error::Error;
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::{env, fmt, io, time};
use walkdir::{DirEntry, WalkDir};

fn main() -> Result<(), Box<dyn Error>> {
    let start = time::Instant::now();
    let args: Vec<String> = env::args().collect();

    let root = parse_path(&args).expect("not a valid path");
    let dir = WalkDir::new(&root);

    let (files, dirs): (Vec<PathBuf>, Vec<PathBuf>) = {
        let pool = pool(dir).expect("unable to retrieve entries from WalkDir");
        partition_from(pool).expect("unable to partition files from directories")
    };

    let (fs_count, dr_count) = (files.len(), dirs.len());
    let (file_counter, total_size) = file_count(files);

    {
        println!("++ File size distribution for: {} ++\n", &root.display());
        println!("Files @ 0B           : {:4}", file_counter[0]);
        println!("Files > 1B  - 1,023B : {:4}", file_counter[1]);
        println!("Files > 1KB - 1,023KB: {:4}", file_counter[2]);
        println!("Files > 1MB - 1,023MB: {:4}", file_counter[3]);
        println!("Files > 1GB - 1,023GB: {:4}", file_counter[4]);
        println!("Files > 1TB+         : {:4}\n", file_counter[5]);

        println!("Files encountered: {}", fs_count);
        println!("Directories traversed: {}", dr_count);
        println!(
            "Total size of all files: {}\n",
            Filesize::<Kilobytes>::from(total_size)
        );
    }

    let end = time::Instant::now();
    println!("Run time: {:?}\n", end.duration_since(start));
    Ok(())
}

fn parse_path(args: &[String]) -> Result<&Path, io::Error> {