use std::{
    fs,
    hash::Hasher,
    hint::black_box,
    io::Write,
    thread,
    time::{Duration, Instant},
};

use ahash::AHasher;
use fhash::FHasher;

use rand::RngCore;

const ITERATIONS: usize = 10_000;

fn main() {
    let mut file = fs::File::create("benchmark.txt").unwrap();
    writeln!(file, "Size\tAHash\tFHash").unwrap();

    for size in 0..256 {
        write!(file, "{}", size).unwrap();

        println!("Size: {}", size);

        let mut hashing_values = Vec::with_capacity(128);
        hashing_values.resize(size, vec![]);

        for bytes in hashing_values.iter_mut() {
            bytes.resize(size, 0);

            rand::thread_rng().fill_bytes(bytes);
        }

        let duration = (0..16)
            .into_iter()
            .map(|_| {
                let mut a_hasher = AHasher::default();

                let start = Instant::now();
                for _ in 0..ITERATIONS {
                    for bytes in &hashing_values {
                        a_hasher.write(black_box(bytes));
                    }
                    black_box(a_hasher.finish());
                }
                Instant::now() - start
            })
            .min()
            .unwrap();

        write!(file, "\t{}", duration.as_micros()).unwrap();

        let duration = (0..16)
            .into_iter()
            .map(|_| {
                let mut shifter_hasher = FHasher::new();

                let start = Instant::now();
                for _ in 0..ITERATIONS {
                    for bytes in &hashing_values {
                        shifter_hasher.write(black_box(bytes));
                    }
                    black_box(shifter_hasher.finish());
                }
                Instant::now() - start
            })
            .min()
            .unwrap();

        writeln!(file, "\t{}", duration.as_micros()).unwrap();

        thread::sleep(Duration::from_millis(25));
    }
}
