use std::{fs, path::Path};
use anyhow::Result;
use crate::lang::{Edition, Lang};
pub const SKIP_C: &str = "⏭";
pub const CHECK_C: &str = "✓";
fn size<P: AsRef<Path>>(path: P) -> std::io::Result<u64> {
let md = fs::metadata(path.as_ref())?;
if md.is_file() {
Ok(md.len())
} else if md.is_dir() {
let mut total = 0;
for entry in fs::read_dir(path)? {
total += size(entry?.path())?;
}
Ok(total)
} else {
Ok(0)
}
}
pub fn human_size(size_bytes: f64) -> String {
let mut size = size_bytes;
for unit in ["B", "KB", "MB"] {
if size < 1024.0 {
return format!("{size:.1} {unit}");
}
size /= 1024.0;
}
format!("{size:.1} GB")
}
pub fn human_time(ms: u128) -> String {
format!("{:.1} s", ms as f64 / 1000.0)
}
fn get_file_size_human<P: AsRef<Path>>(path: P) -> Result<String> {
Ok(human_size(size(path)? as f64))
}
fn pretty_msg_at_path<P: AsRef<Path>>(msg: &str, path: P) -> String {
let path = path.as_ref();
let at = "\x1b[1;36m@\x1b[0m"; match get_file_size_human(path) {
Result::Ok(size_mb) => {
let size_str = format!("\x1b[1m{size_mb}\x1b[0m"); format!("{msg} {at} {} ({})", path.display(), size_str)
}
Err(..) => format!("{msg} {at} {}", path.display()),
}
}
pub fn pretty_println_at_path<P: AsRef<Path>>(msg: &str, path: P) {
println!("{}", pretty_msg_at_path(msg, path));
}
pub fn pretty_print_at_path<P: AsRef<Path>>(msg: &str, path: P) {
print!("{}", pretty_msg_at_path(msg, path));
}
pub fn skip_because_file_exists<P: AsRef<Path>>(skipped: &str, path: P) {
let msg = format!("{SKIP_C} Skipping {skipped}: file already exists");
pretty_println_at_path(&msg, path);
}
pub fn link_wiktionary(edition: Edition, source: Lang, word: &str) -> String {
format!(
"https://{}.wiktionary.org/wiki/{}#{}",
edition,
word.replace(' ', "%20"),
source.long()
)
}
pub fn link_kaikki(edition: Edition, source: Lang, word: &str) -> String {
let chars: Vec<_> = word.chars().collect();
let first = chars[0]; let first_two = if chars.len() < 2 {
word.to_string()
} else {
chars[0..2].iter().collect::<String>()
};
let dictionary = match edition {
Edition::En => "dictionary",
other => &format!("{other}wiktionary"),
};
let localized_source = match edition {
Edition::En | Edition::El => &source.long().replace(' ', "%20"),
_ => "All%20languages%20combined",
};
format!(
"https://kaikki.org/{dictionary}/{localized_source}/meaning/{first}/{first_two}/{word}.html"
)
}