use chrono::*; // For date
use std::fs; // To list files
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use std::process::Command;

/* Execute notify program */
fn notify (text: &String) {
    if cfg!(target_os = "windows") {
        println!("OS not suported");
    } else {
        let _ = Command::new("notify-send")
                .arg("Anniversaires")
                .arg(text)
                .output()
                .expect("failed to execute process");
    }
}

/* Extract birthdate String from vcf file */
fn birthdate (filename: &String) -> String {
    let file = File::open(filename).expect("file not found!");
    let reader = BufReader::new(file);
    for line in reader.lines() {
        let l:String = line.unwrap();
        if l.starts_with("BDAY") {
            return l[5..].to_string();
        }
    }
    return "".to_string()
}

/* Extract full name from vcf file */
fn fullname (filename: &String) -> String {
    let file = File::open(filename).expect("file not found!");
    let reader = BufReader::new(file);
    for line in reader.lines() {
        let l:String = line.unwrap();
        if l.starts_with("FN:") {
            return l[3..].to_string();
        }
    }
    return "".to_string()
}

/* Test if date a is before b in civil year */
fn before_in_civil_year (a :&NaiveDate, b: &NaiveDate) -> bool{
    a.month()*100 + a.day() < b.month()*100 + b.day()
}

fn main() {
    /* Where are the vcf files */
    let vcf_dir = "/home/ilya/.contacts/contacts";
    
    /* How much day before */
    let delta_d = 10;
    
    let tz_today = Local::today();
    let today = NaiveDate::from_ymd(tz_today.year(), tz_today.month(), tz_today.day());

    let paths = fs::read_dir(vcf_dir).unwrap();
    let mut output:String = "".to_string();

    for path in paths {
        /* Get date string from vcf file */
        let filename :String = path.unwrap().path().into_os_string().into_string().unwrap();
        let bdate:String = birthdate(&filename);
        if bdate == "" {
            continue
        }

        /* Parse the date */
        let mut date = match bdate.len() {
            8  => Some(NaiveDate::parse_from_str(&bdate.to_string(), "%Y%m%d").unwrap()),
            10 => Some(NaiveDate::parse_from_str(&bdate.to_string(), "%Y-%m-%d").unwrap()),
            _  => None,
        }.expect("Date is of no known format");

        /* set to y+1 to make it a future date, or to y */
        if before_in_civil_year(&date, &today) {
            date = date.with_year(today.year()+1).unwrap()
        } else {
            date = date.with_year(today.year()).unwrap()
        }
        
        let bdate = UTC.from_local_date(&date).single().unwrap();
        
        /* It is time to be alerted */
        if bdate.num_days_from_ce() - tz_today.num_days_from_ce() <= delta_d {
            output = format!("{}{}/{} {}\n", output, date.day(), date.month(), fullname(&filename));
        }
    }
    notify(&output);
}