use colored::*;
use comfy_table::{Table, Cell, Attribute, Color as TableColor, ContentArrangement};
use indicatif::{ProgressBar, ProgressStyle};
use std::time::Duration;
pub fn print_header(title: &str) {
let width = 60;
let border = "â".repeat(width);
println!("\n{}", border.bright_blue().bold());
println!("{}", format!(" đĨ {} ", title).bright_blue().bold());
println!("{}", border.bright_blue().bold());
}
pub fn print_box(title: &str, content: &[&str]) {
println!("\n{}", format!("ââ {} {}", title, "â".repeat(60 - title.len() - 3)).bright_blue());
for line in content {
println!("{} {}", "â".bright_blue(), line);
}
println!("{}", format!("â{}", "â".repeat(60)).bright_blue());
}
pub fn success(msg: &str) {
println!("{} {}", "â
".green(), msg.green().bold());
}
pub fn info(msg: &str) {
println!("{} {}", "âšī¸ ".bright_blue(), msg.bright_blue());
}
pub fn warning(msg: &str) {
println!("{} {}", "â ī¸ ".yellow(), msg.yellow());
}
pub fn error(msg: &str) {
println!("{} {}", "â".red(), msg.red().bold());
}
pub fn novelty(number: u8, title: &str, content: &[&str]) {
let header = format!("NOVELTY #{}: {}", number, title);
println!("\n{}", format!("ââ {} {}", header, "â".repeat(std::cmp::max(60, header.len() + 4) - header.len() - 3)).bright_magenta().bold());
for line in content {
println!("{} {}", "â".bright_magenta(), line);
}
println!("{}", format!("â{}", "â".repeat(std::cmp::max(60, header.len() + 4))).bright_magenta());
}
pub fn create_progress_bar(total: u64, message: &str) -> ProgressBar {
let pb = ProgressBar::new(total);
pb.set_style(
ProgressStyle::default_bar()
.template("{msg}\n{spinner:.green} [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})")
.unwrap()
.progress_chars("ââââ "),
);
pb.set_message(message.to_string());
pb
}
pub fn create_spinner(message: &str) -> ProgressBar {
let pb = ProgressBar::new_spinner();
pb.set_style(
ProgressStyle::default_spinner()
.template("{spinner:.green} {msg}")
.unwrap()
.tick_strings(&["â ", "â ", "â š", "â ¸", "â ŧ", "â ´", "â Ļ", "â §", "â ", "â "]),
);
pb.set_message(message.to_string());
pb.enable_steady_tick(Duration::from_millis(80));
pb
}
pub fn print_comparison_table(rows: Vec<(&str, &str, &str, &str)>) {
let mut table = Table::new();
table
.set_content_arrangement(ContentArrangement::Dynamic)
.set_header(vec![
Cell::new("File").fg(TableColor::Cyan).add_attribute(Attribute::Bold),
Cell::new("Strategy").fg(TableColor::Cyan).add_attribute(Attribute::Bold),
Cell::new("Time").fg(TableColor::Cyan).add_attribute(Attribute::Bold),
Cell::new("Size").fg(TableColor::Cyan).add_attribute(Attribute::Bold),
]);
for (file, strategy, time, size) in rows {
table.add_row(vec![
Cell::new(file),
Cell::new(strategy).fg(TableColor::Green),
Cell::new(time),
Cell::new(size),
]);
}
println!("\n{}", table);
}
pub fn print_network_topology(local_peers: &[(String, u32)], regional_peers: &[(String, u32)], global_peers: &[(String, u32)]) {
println!("\n{}", "đ FireCloud Network Topology (Live)".bright_cyan().bold());
println!();
println!("{}", "YOU (local-node)".bright_white().bold());
println!(" â");
if !local_peers.is_empty() {
println!(" {}", "ââ LOCAL (mDNS) âââââââââââââââââ".bright_green());
for (i, (name, latency)) in local_peers.iter().enumerate() {
let prefix = if i == local_peers.len() - 1 { "ââ" } else { "ââ" };
println!(" â {} đģ {} ({}ms)", prefix.bright_green(), name, latency.to_string().bright_green());
}
println!(" â");
}
if !regional_peers.is_empty() {
println!(" {}", "ââ REGIONAL (DHT) âââââââââââââââ".yellow());
for (i, (name, latency)) in regional_peers.iter().enumerate() {
let prefix = if i == regional_peers.len() - 1 { "ââ" } else { "ââ" };
println!(" â {} đĨī¸ {} ({}ms)", prefix.yellow(), name, latency.to_string().yellow());
}
println!(" â");
}
if !global_peers.is_empty() {
println!(" {}", "ââ GLOBAL (DHT) âââââââââââââââââ".red());
for (i, (name, latency)) in global_peers.iter().enumerate() {
let prefix = if i == global_peers.len() - 1 { "ââ" } else { "ââ" };
println!(" {} đ {} ({}ms)", prefix.red(), name, latency.to_string().red());
}
}
}
pub fn print_piece_distribution(file_name: &str, file_size: &str, local: usize, regional: usize, global: usize) {
println!("\n{}", format!("File: {} ({})", file_name, file_size).bright_white().bold());
println!("{}", "Pieces distributed:".bright_white());
let local_pieces = "đĸ".repeat(local);
let regional_pieces = "đĄ".repeat(regional);
let global_pieces = "đ´".repeat(global);
println!(" {} Local ({} pieces - fast reads)", local_pieces, local);
println!(" {} Regional ({} pieces - medium)", regional_pieces, regional);
println!(" {} Global ({} piece - durability)", global_pieces, global);
println!("\n{}", "This is NOVELTY #3 in action! âĄ".bright_magenta().bold());
}
pub fn print_benchmark(name: &str, our_time: f64, their_time: f64, speedup: f64) {
println!("\n{}", format!("đ Benchmark: {}", name).bright_cyan().bold());
println!();
let our_bar = "â".repeat((our_time / their_time * 40.0) as usize);
let their_bar = "â".repeat(40);
println!("{}", "Dropbox:".bright_white());
println!("{} {:.1}s", their_bar.red(), their_time);
println!();
println!("{}", "FireCloud:".bright_white());
println!("{} {:.1}s", our_bar.green(), our_time);
println!();
println!("{} {}", "đ FireCloud is".green().bold(), format!("{:.1}x FASTER!", speedup).green().bold());
}
pub fn print_status(network_mode: &str, local_peers: usize, dht_peers: usize, storage_used: f64, storage_total: f64, shares_active: usize, shares_pending: usize) {
println!("\nââââââââââââââââââââââââââââââââââââââââââ");
println!("â {} {} â", "đĨ".bright_yellow(), "FireCloud Status".bright_white().bold());
println!("ââââââââââââââââââââââââââââââââââââââââââ¤");
println!("â {}: {} â", "Network Mode".bright_cyan(), network_mode.bright_white());
println!("â {} {} peers discovered â", " âĸ".bright_green(), local_peers.to_string().bright_green());
println!("â {} {} peers in routing â", " âĸ".bright_blue(), dht_peers.to_string().bright_blue());
let storage_pct = (storage_used / storage_total * 100.0) as usize;
let storage_bar = "â".repeat(storage_pct / 4);
let storage_empty = "â".repeat(25 - storage_pct / 4);
println!("â {}: {:.1} GB / {:.1} GB ({}%) â", "Storage".bright_cyan(), storage_used, storage_total, storage_pct);
println!("â [{}{}] â", storage_bar.bright_green(), storage_empty.bright_black());
println!("â {}: {} active | {} pending â", "Shares".bright_cyan(), shares_active.to_string().bright_white(), shares_pending.to_string().bright_yellow());
println!("ââââââââââââââââââââââââââââââââââââââââââ");
}