use crate::{Pick, TakoyakiError};
use colored::*;
use serde_json::Value;
#[derive(Default, Clone, PartialEq, Debug, Eq)]
pub struct Printable {
pub color: String,
pub count: i64,
}
#[derive(Default, Clone, PartialEq, Debug, Eq)]
pub struct PrintableGrid<'a> {
pick: Pick<'a>,
data: serde_json::Value,
pub grid: Vec<Vec<Printable>>,
}
impl<'a> PrintableGrid<'a> {
pub fn new(pick: Pick<'a>, data: serde_json::Value) -> Self {
Self {
pick,
data,
grid: vec![],
}
}
pub fn insert_at(&mut self, x: usize, y: usize, item: Printable) {
if self.grid.len() <= x {
self.grid.resize(x + 1, vec![])
}
if self.grid[x].len() <= y {
self.grid[x].resize(y, Printable::default())
}
self.grid[x].insert(y, item);
}
fn print(&self) -> Result<(), TakoyakiError> {
let config = crate::Config::new()?;
for row in &self.grid {
for item in row {
let fallback = serde_yaml::Value::String(item.color.clone());
let color = config
.colors
.get(format!("{}_contribution", item.count))
.or(config.colors.get("x_contribution"))
.unwrap_or(&fallback)
.as_str()
.unwrap();
let rgb = colorsys::Rgb::from_hex_str(color)?;
if config.unicode.paint_bg {
print!(
"{}",
config.unicode.character.on_truecolor(
rgb.red() as u8,
rgb.green() as u8,
rgb.blue() as u8
)
)
} else {
print!(
"{}",
config.unicode.character.truecolor(
rgb.red() as u8,
rgb.green() as u8,
rgb.blue() as u8
)
)
}
}
println!()
}
Ok(())
}
fn iterate_through_value(
&self,
json: &'a Value,
keys: &'a str,
) -> Result<&'a Value, TakoyakiError> {
keys.split('.')
.fold(Some(json), |prev, next| {
prev.and_then(|value| value.get(next))
})
.ok_or(TakoyakiError::RootNotFound(keys.to_string()))
}
pub fn pretty_print(&mut self) -> Result<(), TakoyakiError> {
let root_clone = &self.data.clone();
let weeks_list = self
.iterate_through_value(root_clone, self.pick.array_root)?
.as_array()
.ok_or(TakoyakiError::UnexpectedType("Vec<Value>".to_string()))?;
let mut x = 0;
for (y, week) in weeks_list.iter().enumerate() {
let days_list = self
.iterate_through_value(week, self.pick.weeks_root)?
.as_array()
.ok_or(TakoyakiError::UnexpectedType("Vec<Value>".to_string()))?;
for day in days_list {
self.insert_at(
x,
y,
Printable {
color: self
.iterate_through_value(day, self.pick.color_key)
.unwrap()
.as_str()
.unwrap()
.to_string(),
count: self
.iterate_through_value(day, self.pick.contribution_count_key)
.unwrap()
.as_i64()
.unwrap(),
},
);
x += 1;
}
x = 0;
}
self.print()?;
Ok(())
}
}