use std::time::Duration;
use serde::{Deserialize, Serialize};
use crate::{
bank::Bank,
cycle::Cycle,
envelope::{current_time, euros_on_track, percentage_between, Envelope},
euro::Euros,
frontend::Color,
EnvelopeId,
};
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
pub enum SavingGoal {
#[default]
None,
Amount(Euros),
SavingGoal {
start: Duration,
end: Duration,
amount: Euros,
},
Spending {
cycle: Cycle,
amount: Euros,
},
SavingBuilding {
amount: Euros,
},
}
impl SavingGoal {
pub fn color_status(&self, bank: &Bank, envelope: EnvelopeId) -> Color {
let assigned = bank.assigned(envelope);
match self {
SavingGoal::None => Color::Green,
SavingGoal::Amount(val) => {
if val.total_cents() <= assigned.total_cents() {
Color::Green
} else {
Color::Yellow
}
}
SavingGoal::SavingGoal { start, end, amount } => {
let now = current_time();
if now > *end {
if assigned.total_cents() >= amount.total_cents() {
Color::Green
} else {
Color::Red
}
} else {
let track = euros_on_track(now, *start, *end, *amount);
if track.total_cents() > assigned.total_cents() {
Color::Yellow
} else {
Color::Green
}
}
}
SavingGoal::Spending { cycle, amount } => {
if assigned.total_cents() < 0 {
return Color::Red;
}
let spent = bank.money_spent_in_timeframe(envelope, cycle.start(), cycle.end());
if assigned.total_cents() + spent.total_cents() >= amount.total_cents() {
Color::Green
} else {
Color::Red
}
}
SavingGoal::SavingBuilding { amount } => {
let assigned =
bank.assigned_in_timeframe(envelope, Cycle::Week.start(), Cycle::Week.end());
if assigned.total_cents() < amount.total_cents() {
Color::Yellow
} else {
Color::Green
}
}
}
}
pub fn is_none(&self) -> bool {
matches!(self, Self::None)
}
pub fn display(&self, bank: &Bank, envelope: &Envelope) -> String {
let assigned = bank.assigned(envelope.id());
match self {
SavingGoal::None => assigned.print(),
SavingGoal::Amount(eur) => {
format!("{}/{}", assigned.print(), eur.print())
}
SavingGoal::SavingGoal { start, end, amount } => {
let percentage = percentage_between(current_time(), *start, *end);
let final_goal = *amount;
let current_track: Euros = ((f32::from(final_goal)) * percentage).into();
format!("{}/{}", assigned.print(), current_track.print())
}
SavingGoal::Spending { cycle, amount } => {
let start = cycle.start();
let end = cycle.end();
let moneystuff = bank.money_spent_in_timeframe(envelope.id(), start, end);
let assigned = assigned + moneystuff;
let track = euros_on_track(current_time(), start, end, *amount);
let cycles_paid = f32::from(assigned) / f32::from(*amount);
let s = format!(
"track: {}, spent: {}, total assigned: {}, goal: {}, paid cycles: {}",
track.print(),
moneystuff.print(),
assigned.print(),
amount.print(),
cycles_paid
);
s
}
SavingGoal::SavingBuilding { amount } => {
let assigned_in_cycle = bank.assigned_in_timeframe(
envelope.id(),
Cycle::Week.start(),
Cycle::Week.end(),
);
format!("{}/{}", assigned_in_cycle.print(), amount.print())
}
}
}
}