extern crate termion;
use crate::error::{TimebarError, TimebarResult};
use crate::helpers::{get_percentage, get_time_left, limit_name, print_bar, string_to_u32};
use crate::{APP_INFO, PREF_LIFE};
use chrono::NaiveDate;
use preferences::Preferences;
use std::io::stdin;
use std::process;
use std::thread;
use std::time::Duration;
use termion::{clear, color, cursor};
pub fn life_handler(args: Vec<String>) {
if args.len() == 3 {
let option = &args[2];
let save = String::from("-s");
match option {
_ if option == &save => life_flow(true),
_ => display_by_name(option),
}
} else if args.len() == 2 {
life_flow(false);
} else {
println!("Please enter valid arguments.");
}
}
fn display_by_name(option: &str) {
let existing_lives = Vec::<LifeConfig>::load(&APP_INFO, PREF_LIFE).unwrap();
for life in existing_lives {
if life.name == option {
let (start, end, lifespan) = config_to_draw_input(life.clone());
display_life(start, end, lifespan, &life.name);
return;
}
}
println!("There is no life entry saved on that name.");
}
fn config_to_draw_input(config: LifeConfig) -> (u64, u64, u32) {
let start = NaiveDate::from_ymd(config.year as i32, config.month, config.day)
.and_hms(0, 0, 0)
.timestamp() as u64;
let lifespan = config.lifespan;
let end = NaiveDate::from_ymd((config.year + lifespan) as i32, config.month, config.day)
.and_hms(0, 0, 0)
.timestamp() as u64;
(start, end, lifespan)
}
fn display_life(start: u64, end: u64, lifespan: u32, name: &str) {
println!("\n{}{}", clear::All, cursor::Goto(1, 1));
loop {
draw(start, end, "life", lifespan, name);
thread::sleep(Duration::from_millis(1000));
println!("\n{}{}{}", cursor::Show, clear::All, cursor::Goto(1, 1));
}
}
fn draw(start: u64, end: u64, display_type: &str, lifespan: u32, name: &str) {
let percentage = get_percentage(start, end);
let info = get_time_left(end, display_type.to_string()).unwrap();
print!("{}", color::Fg(color::White));
print_bar(&percentage);
println!(
"\n{} is expected to exist on this planet for {} years.",
name, lifespan
);
println!("\nTime remaining:");
println!("{}", color::Fg(color::Green));
println!("{} in years", info.years);
println!("{} in months", info.months);
println!("{} in weeks", info.weeks);
println!("{} in days", info.days);
println!("{} in hours", info.hours);
println!("{} in minutes", info.minutes);
println!(
"{}{}{} in seconds.",
color::Fg(color::Yellow),
info.seconds,
color::Fg(color::Green)
);
println!("\n{}Have a good day!", color::Fg(color::White));
}
fn life_flow(should_save: bool) {
print_life_intro();
let mut args = String::new();
stdin().read_line(&mut args).expect("Failed to read line");
let config = LifeConfig::new(args.split(' ').collect()).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {}", err);
process::exit(1);
});
if should_save {
let mut lives = Vec::<LifeConfig>::load(&APP_INFO, PREF_LIFE).unwrap_or(Vec::new());
lives.push(config.clone());
let save_result = lives.save(&APP_INFO, PREF_LIFE);
assert!(save_result.is_ok());
}
let (start, end, lifespan) = config_to_draw_input(config.clone());
display_life(start, end, lifespan, &config.name);
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct LifeConfig {
pub name: String,
pub day: u32,
pub month: u32,
pub year: u32,
pub lifespan: u32,
}
impl LifeConfig {
pub fn new(args: Vec<&str>) -> TimebarResult<LifeConfig> {
let mut iterator = args.into_iter();
let name = match iterator.next() {
Some(arg) => limit_name(arg),
None => return Err(TimebarError::InvalidInput("name".to_string())),
};
let birthday = match iterator.next() {
Some(arg) => arg,
None => return Err(TimebarError::InvalidInput("birthday".to_string())),
};
let lifespan = match iterator.next() {
Some(arg) => arg,
None => return Err(TimebarError::InvalidInput("lifespan".to_string())),
};
let birthday: Vec<&str> = birthday.split('/').collect();
if birthday.len() != 3 {
return Err(TimebarError::InvalidDateFormat);
}
let day = string_to_u32(birthday[0].clone().trim()).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {}", err);
process::exit(1);
});
let month = string_to_u32(birthday[1].clone().trim()).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {}", err);
process::exit(1);
});
let year = string_to_u32(birthday[2].clone().trim()).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {}", err);
process::exit(1);
});
let lifespan = string_to_u32(lifespan.clone().trim()).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {}", err);
process::exit(1);
});
Ok(LifeConfig {
name,
day,
month,
year,
lifespan,
})
}
}
fn print_life_intro() {
println!("Enter your name, birthday and your expected lifespan.");
println!(
"For example: {}Brian 21/3/1985 101{}",
color::Fg(color::Green),
color::Fg(color::White)
);
}