use std::io::{BufRead, BufReader};
use std::path::{PathBuf, Path};
use std::fs::File;
use itertools::Itertools;

use structopt::StructOpt;


#[derive(StructOpt, Debug)]
struct Opt {
    /// Input file
    #[structopt(parse(from_os_str))]
    input_file: PathBuf,
}

fn main() {
    // Check argv
    let opts = Opt::from_args();
    // eprintln!("opts = {:?}",   opts);
    // Load file if possible
    let file_path = Path::new(&opts.input_file);
    let input = File::open(file_path).unwrap();
    let buffered_input = BufReader::new(input);
    let lines: Vec<String> = buffered_input.lines().filter_map(Result::ok).collect();
    // eprintln!("lines_iter = {:?}", lines_iter);

    /* First, naïve solution */
    // while let Some(line) = lines_iter.next() {
    //     let iter_clone = lines_iter.clone();
    //     // eprintln!("iter_clone = {:#?}", iter_clone);
    //     for line2 in iter_clone {
    //         let l1: i64 = line.parse().unwrap();
    //         let l2: i64 = line2.parse().unwrap();
    //         if l1 + l2 == 2020 {
    //             eprintln!("l1 = {:#?}", l1);
    //             eprintln!("l2 = {:#?}", l2);
    //             dbg!(l1 + l2);
    //             dbg!(l1 * l2);
    //         }
    //     }
    // }

    let res_two = find_2_sum_to_2020(lines.iter().filter_map(|x| Result::ok(x.parse::<i64>())).collect());
    let res_three = find_3_sum_to_2020(lines.iter().filter_map(|x| Result::ok(x.parse::<i64>())).collect());
    //let res_three = find_sum_to_2020(3);
}

fn find_3_sum_to_2020(numbers: Vec<i64>) -> Option<(i64,i64, i64)> {
    for (i,j, k) in numbers.into_iter().tuple_combinations() {
        if i + j + k == 2020 {
            println!("Found {} and {} and {} whose sum is {} and whose product is {}", i, j, k, i+j+k, i*j*k);
            return Some((i,j,k));
        }
    }
    None
}

fn find_2_sum_to_2020(numbers: Vec<i64>) -> Option<(i64,i64)> {
    for (i,j) in numbers.iter().tuple_combinations() {
        if i + j == 2020 {
            println!("Found {} and {} whose sum is {} and whose product is {}", i, j, i+j, i*j);
            return Some((*i,*j));
        }
    }
    None
}
