use std::io::{self, Write, BufRead};
use std::thread;
use std::time::Duration;
use utls::{prog::{PBStyle, PB, Spinner}, traits::decl::Empty};
fn main() {
let mut pb = PB::EMPTY;
let stdin = io::stdin();
let mut stdout = io::stdout();
let mut input = String::new();
print!("Enter maximum value for the progress bar: ");
stdout.flush().unwrap();
stdin.lock().read_line(&mut input).unwrap();
pb.max = input.trim().parse().unwrap_or(100);
println!("\nAvailable styles:");
println!("1. Classic ([#### ] 40%)");
println!("2. Modern (│████░░░░│ 40/100 (40%))");
println!("3. Minimal (====>---- 40%)");
println!("4. Fancy (『■■■□□□』40/100 • 40% • 0:00:04.123)");
println!("5. ASCII ((***...) 40%)");
println!("6. Dots (⣿⣿⣿⠒⠒⠒ 40%)");
println!("7. Arrows (◀▶▶▶▶▷▷▷▷◀▶ 40%)");
println!("8. Box Heavy(┣████░░░░┫ 40/100 (40%))");
print!("Choose style (1-8): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
pb.style = match input.trim() {
"2" => PBStyle::modern(),
"3" => PBStyle::minimal(),
"4" => PBStyle::fancy(),
"5" => PBStyle::ascii(),
"6" => PBStyle::dots(),
"7" => PBStyle::arrows(),
"8" => PBStyle::box_heavy(),
_ => PBStyle::classic(),
};
println!("\n=== Advanced Configuration ===");
print!("Enter bar width (10-100): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
pb.conf.width = input.trim().parse().unwrap_or(50).clamp(10, 100);
print!("Enter update delay in milliseconds (50-1000): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
let delay_ms = input.trim().parse().unwrap_or(100).clamp(50, 1000);
pb.conf.update_freq = Duration::from_millis(delay_ms as u64);
print!("Enter message format (leave empty for default): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
let message = input.trim().to_string();
if !message.is_empty() {
pb.style.message = message;
}
print!("Enter description (leave empty for none): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
let desc = input.trim().to_string();
if !desc.is_empty() {
pb.style.desc = desc;
}
print!("Add spinner? (y/N): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
if input.trim().eq_ignore_ascii_case("y") {
print!("Enter spinner characters (e.g., '|/-\\'): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
let spinner_chars = input.trim();
if !spinner_chars.is_empty() {
pb.style.spinner = Some(Spinner::new(spinner_chars));
print!("Enter spinner update frequency in ms (50-1000): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
let spinner_freq = input.trim().parse().unwrap_or(100).clamp(50, 1000);
pb.conf.spinner_update_freq = Duration::from_millis(spinner_freq);
}
}
print!("Enter decimal precision for percentages (0-5): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
pb.style.prec = input.trim().parse().unwrap_or(0).clamp(0, 5);
print!("Enter bar end character (leave empty for default): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
let bar_end = input.trim().to_string();
if !bar_end.is_empty() {
pb.style.bar_end = bar_end;
}
print!("Enable advanced statistics? (y/N): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
pb.conf.stats.adv_enabled = input.trim().eq_ignore_ascii_case("y");
print!("Enable update deferral? (y/N): ");
stdout.flush().unwrap();
input.clear();
stdin.lock().read_line(&mut input).unwrap();
pb.conf.defer_updates = input.trim().eq_ignore_ascii_case("y");
pb.conf.formatting = true;
pb.conf.bar = true;
println!("\nEquivalent builder code:");
println!("let pb = PB::builder({})", pb.max);
println!(" .style(PBStyle::{}())", match pb.style {
_ if pb.style.endcaps == PBStyle::modern().endcaps => "modern",
_ if pb.style.endcaps == PBStyle::minimal().endcaps => "minimal",
_ if pb.style.endcaps == PBStyle::fancy().endcaps => "fancy",
_ if pb.style.endcaps == PBStyle::ascii().endcaps => "ascii",
_ if pb.style.endcaps == PBStyle::dots().endcaps => "dots",
_ if pb.style.endcaps == PBStyle::arrows().endcaps => "arrows",
_ if pb.style.endcaps == PBStyle::box_heavy().endcaps => "box_heavy",
_ => "classic",
});
println!(" .width({})", pb.conf.width);
println!(" .update_frequency(Duration::from_millis({}))", delay_ms);
if !pb.style.message.is_empty() {
println!(" .message(\"{}\")", pb.style.message);
}
if !pb.style.desc.is_empty() {
println!(" .description(\"{}\")", pb.style.desc);
}
if let Some(ref spinner) = pb.style.spinner {
println!(" .spinner_chars(\"{}\")", spinner.chars.iter().collect::<String>());
println!(" .spinner_freq(Duration::from_millis({}))",
pb.conf.spinner_update_freq.as_millis());
}
if pb.style.prec > 0 {
println!(" .precision({})", pb.style.prec);
}
if !pb.style.bar_end.is_empty() {
println!(" .bar_end(\"{}\")", pb.style.bar_end);
}
if pb.conf.stats.adv_enabled {
println!(" .adv_stats(true)");
}
if pb.conf.defer_updates {
println!(" .defer(true)");
}
println!(" .build();");
println!("\nPress Enter to start the progress bar...");
input.clear();
stdin.lock().read_line(&mut input).unwrap();
let (handle, pb_arc) = pb.threaded_start();
while let Ok(mut guard) = pb_arc.lock() {
if guard.current >= guard.max {
break;
}
guard.inc();
drop(guard);
thread::sleep(pb.conf.update_freq);
}
pb_arc.lock().unwrap().finish();
handle.join().unwrap();
}