use itertools::Itertools;

fn main() {
    let input = include_str!("../data/input");
    let input_slice = parse(input);
    let step1 = brk_enc_step1(&input_slice, 25).unwrap();
    println!("Step 1: {}", step1);
    let step2 = brk_enc_step2(&input_slice, *step1).unwrap();
    println!("Step 2: {}", step2);
}

fn brk_enc_step1<'a, U>(input: &'a[U], window_size: usize) -> Option<&'a U> where
    U: PartialEq,
    &'a U: std::ops::Add<Output = U> {
        input
            .windows(window_size + 1)
            .find(
                |&w| {
                    let last = w.last().unwrap();
                    let firsts = w[..(w.len()-1)].iter().combinations(2);
                    !firsts.map(|f | {
                        *f.first().unwrap() + *f.last().unwrap() == *last
                    }).any(|t|t)
                }
            )?.last()
}

fn brk_enc_step2<'a, U>(input: &'a[U], s1key: U) -> Option<U> where
    U: PartialEq + std::cmp::Ord + std::iter::Sum<&'a U>,
    &'a U: std::ops::Add<Output = U> {
        (2..input.len())
            .find_map(|x| {
                input
                    .windows(x)
                    .find_map(|w| {
                        if w.iter().sum::<U>() == s1key {
                            Some(w.iter().min().unwrap() + w.iter().max().unwrap())
                        } else {
                            None
                        }
                })
            })
            //     (input)
            // .find(|w| {
            //     w.sum() == s1key
            // })
}

fn parse(input: &'static str) -> Vec<i64> {
    input
        .lines()
        .map(|l| l.parse::<i64>().unwrap())
        .collect()
}

#[cfg(test)]
mod tests {
    use super::*;
    static INPUT: &str = r"35
20
15
25
47
40
62
55
65
95
102
117
150
182
127
219
299
277
309
576";

    #[test]
    fn test_step1() {
        assert_eq!(brk_enc_step1(&parse(INPUT), 5), Some(&127));
    }

    #[test]
    fn test_step2() {
        let a = brk_enc_step2(&parse(INPUT), 127i64).unwrap();
        assert_eq!(a, 62);
    }
}