use std::env;
use std::fs;
use std::io::{BufReader, BufRead, ErrorKind};
use regex::Regex;
use chrono::{Datelike, Duration, offset::Local, NaiveDate, Weekday};
use timelogging::timetracking::{process_input_file, generate_individual_timecards};

fn main() {

    // Regular Expressions
    let offset      = Regex::new(r"^[+-]*\d+").unwrap();

    // Process options
    let params: Vec<String> = env::args().collect();

    // If week offset is provided, grab it
    let mut week_offset: i64 = 0;
    for arg in &params {
        if offset.is_match(&arg.to_string()) {
            week_offset = arg.parse::<i64>().unwrap();
        };
    };

    let day: NaiveDate = last_monday(week_offset);
    let mut filenames: Vec<String> = Vec::new();
    for d in 0..7 {
        filenames.push((day + Duration::days(d)).format("%Y-%m-%d.log").to_string());
    };

    assert_eq!(filenames.len(), 7);

    let mut grand_total: f64 = 0.0;
    for filename in filenames {
        println!("{} ", filename);
        // Process the file
        let mut gtoth = match fs::File::open(filename) {
            Ok(file) => {
                // Hash Maps (akin to Python Dictionaires)
                let mut reader: Box<dyn BufRead> = Box::new(BufReader::new(file));
                // For each line of input (build internal data structures)
                let (mut start, mut finish, _) = process_input_file(&mut reader);
                // generate total for this file
                let (_, total) = generate_individual_timecards(&mut start, &mut finish);
                total
            },
            Err(error) => match error.kind() {
                ErrorKind::NotFound => 0.0,
                _ => panic!("Error reading file! Error:  {}", error)
            }
        };
        if gtoth > 24.0 {
            gtoth = 24.0;
        };
        // print the output
        println!("{}", format!("{:.2}", gtoth));
        println!();
        grand_total += gtoth;
    };
    println!("Grand total: {:.2}", grand_total);
}

fn last_monday(offset: i64) -> NaiveDate {
    let day: NaiveDate = Local::today().naive_local() - Duration::days(7 * offset);
    match day.weekday() {
        Weekday::Mon => day - Duration::days(0),
        Weekday::Tue => day - Duration::days(1),
        Weekday::Wed => day - Duration::days(2),
        Weekday::Thu => day - Duration::days(3),
        Weekday::Fri => day - Duration::days(4),
        Weekday::Sat => day - Duration::days(5),
        Weekday::Sun => day - Duration::days(6)
    }
}
