use std::fmt::Write;

use indicatif::{ProgressBar, ProgressState, ProgressStyle};

pub fn constuct_progress_bar(
    total_frame: u64,
    resume_frames: u64,
    progress_template: Option<String>,
    is_smart: bool,
) -> ProgressBar {
    let real_template = if is_smart {
        progress_template.unwrap_or(
            "{elapsed_precise:.bold} ▐{wide_bar:.blue/white.dim}▌ {percent:.bold}% {pos}/{len} \
             ({fps:.bold}, eta {eta})"
                .to_string(),
        )
    } else {
        progress_template.unwrap_or(
            "{elapsed_precise:.bold} ▐{wide_bar:.blue/white.dim}▌ {percent:.bold}% {pos}/{len} \
             ({fps:.bold}, eta {eta} | Scenes: {msg})"
                .to_string(),
        )
    };

    let pb = ProgressBar::new(total_frame);

    pb.set_style(
        ProgressStyle::with_template(&real_template)
            .expect("template is valid")
            .with_key("fps", move |state: &ProgressState, w: &mut dyn Write| {
                let resume_pos = if state.pos() < resume_frames {
                    resume_frames
                } else {
                    state.pos() - resume_frames
                };
                if resume_pos == 0 || state.elapsed().as_secs_f64() < f64::EPSILON {
                    write!(w, "0 fps").unwrap();
                } else {
                    let fps = resume_pos as f64 / state.elapsed().as_secs_f64();
                    if fps < 1.0 {
                        write!(w, "{:.2} s/fr", 1.0 / fps).unwrap();
                    } else {
                        write!(w, "{fps:.2} fps").unwrap();
                    }
                }
            }),
    );
    pb
}
