use std::iter;
use std::fs;
use std::env;
use topological_sort::TopologicalSort;

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
struct Rule ( i32, i32 );

fn main() {
    println!("Hello, AoC day 05!");

    let args: Vec<String> = env::args().collect();
    if args.len() != 2 {
        println!("wrong number of arguments!");
        std::process::exit(1);
    }

    let file_path = &args[1];

    let contents = fs::read_to_string(file_path).expect("Should have been able to read the file");
    let (first, second) = contents.split_once("\n\n").unwrap();

    let rules: Vec<Rule> = first
        .lines()
        .map(|line| {
            let (before, after) = line.split_once("|").unwrap();
            Rule(before.parse().unwrap(), after.parse().unwrap())
        })
        .collect();
    let updates = second.lines();

    let mut good_sum: i32 = 0;
    let mut bad_sum: i32 = 0;
    for update in updates {
        let pages: Vec<i32> = update
            .split(",")
            .map(|page| page.parse::<i32>().unwrap())
            .collect();

        let mut my_sort: TopologicalSort::<i32> = TopologicalSort::new();

        rules
            .iter()
            .filter(|&Rule(a, b)| pages.contains(a) && pages.contains(b))
            .for_each(|&Rule(a, b)| my_sort.add_dependency(a, b));

        let true_pages: Vec<i32> = iter::from_fn(|| my_sort.pop())
            .filter(|p| pages.contains(p))
            .collect();

        let middle: i32 = true_pages.get((true_pages.len() - 1) / 2)
            .expect("error finding the halfway point");

        if iter::zip(pages.iter(), true_pages.iter()).all(|(a, b)| a==b) {
            // it's good!
            good_sum += middle;
        } else {
            // it's bad!
            bad_sum += middle;
        }
       
    }

    println!("the sum of middle pages of good updates is {good_sum}");
    println!("and the bad updates is {bad_sum}");
}