mod solutions;
mod utils;

use std::{error::Error, time::SystemTime};

use solutions::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let days: Vec<Box<dyn Solution + Sync>> = vec![
        Box::new(day01::Day01 {}),
        Box::new(day02::Day02 {}),
        Box::new(day03::Day03 {}),
        Box::new(day04::Day04 {}),
        Box::new(day05::Day05 {}),
        Box::new(day06::Day06 {}),
        Box::new(day07::Day07 {}),
        Box::new(day08::Day08 {}),
        Box::new(day09::Day09 {}),
        Box::new(day10::Day10 {}),
        Box::new(day11::Day11 {}),
        // Box::new(day12::Day12 {}),
        // Box::new(day13::Day13 {}),
        // Box::new(day14::Day14 {}),
        // Box::new(day15::Day15 {}),
        // Box::new(day16::Day16 {}),
        // Box::new(day17::Day17 {}),
        // Box::new(day18::Day18 {}),
        // Box::new(day19::Day19 {}),
        // Box::new(day20::Day20 {}),
        // Box::new(day21::Day21 {}),
        // Box::new(day22::Day22 {}),
        // Box::new(day23::Day23 {}),
        // Box::new(day24::Day24 {}),
        // Box::new(day25::Day25 {}),
    ];

    let mut t = vec![];

    // Run through and generate solutions
    for day in days.leak() {
        let task = tokio::spawn(async { day.run().unwrap() });
        t.push(task);
    }

    let start_time = SystemTime::now();

    let mut days = vec![];
    for thread in t {
        days.push(thread.await?);
    }

    for day in days {
        println!("========= Day {} ==========", day.day);
        println!("Part1 Result: {}", day.part1);
        println!("Part2 Result: {}", day.part2);
        println!("========= {}ms =========\n", day.time.as_millis());
    }

    println!(
        "Ran AoC 2023 in {}ms",
        SystemTime::now().duration_since(start_time)?.as_millis()
    );
    Ok(())
}