//! Types for abstracting over communicating with the user, with support for
//! mocking in tests.
//!
//! In general, this type should be preferred over directly writing to stdout or
//! stderr.

use crate::git_tool::Editor;
use console::{Style, Term};
use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressStyle};
use lazy_static::lazy_static;
use std::{borrow::Cow, fmt, fs::File, io, mem, time::Duration};

/// Object-safe extension of `std::io::Write` with extra features for
/// interacting with the terminal. Can be mocked in tests to allow them to test
/// other features.
pub trait Out: Send + Sync + 'static {
    /// Write to the output.
    fn write(&self, buf: &[u8]) -> io::Result<usize>;

    /// Write to the output
    fn write_fmt(&self, args: fmt::Arguments<'_>) {
        struct AsWrite<'a, T: ?Sized>(&'a T);
        impl<'a, T: ?Sized + Out> io::Write for AsWrite<'a, T> {
            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
                Out::write(self.0, buf)
            }

            fn flush(&mut self) -> io::Result<()> {
                Ok(())
            }
        }

        io::Write::write_fmt(&mut AsWrite(self), args).unwrap();
    }

    /// Check if this output is a real terminal.
    fn is_term(&self) -> bool {
        false
    }

    /// If the user is interacting through a terminal, clear the screen.
    /// Should fail silently if the screen cannot be cleared.
    fn clear_screen(&self) -> io::Result<()> {
        Ok(())
    }

    /// Ask the user a question, and read in a line with the user's response. If
    /// there's no user able to respond, an error will be returned instead.
    fn read_line_with_prompt(&self, _prompt: &str) -> io::Result<String> {
        Err(io::ErrorKind::Unsupported.into())
    }

    /// Get a `Style` object which can be used to style text written to this
    /// user. Defaults to a disabled style object.
    fn style(&self) -> Style {
        Style::new().force_styling(false)
    }

    /// Create an editor to prompt the user with.
    /// Exists primarily to allow tests to mock out this feature, and block
    /// editor usage when using a file output.
    fn editor<'a>(&'a self, _name: &'a str) -> io::Result<Editor<'a>> {
        Err(io::ErrorKind::Unsupported.into())
    }
}

// "Real" user-facing terminal on stdout
impl Out for Term {
    fn write(&self, buf: &[u8]) -> io::Result<usize> {
        // XXX: Consider suspending the MultiProgress when writing if we ever
        // want to write to `Out` while a progress bar is rendering.
        io::Write::write(&mut &*self, buf)
    }

    fn is_term(&self) -> bool {
        self.is_term()
    }

    fn clear_screen(&self) -> io::Result<()> {
        self.clear_screen()
    }

    fn read_line_with_prompt(&self, prompt: &str) -> io::Result<String> {
        self.write_str(prompt)?;
        self.flush()?;
        self.read_line()
    }

    fn style(&self) -> Style {
        self.style()
    }

    fn editor(&self, name: &str) -> io::Result<Editor<'_>> {
        Editor::new(name)
    }
}

// File based output with no special features.
impl Out for File {
    fn write(&self, buf: &[u8]) -> io::Result<usize> {
        io::Write::write(&mut &*self, buf)
    }
}

impl io::Write for &'_ dyn Out {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        Out::write(*self, buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

lazy_static! {
    /// The global `MultiProgress` which can be used to write out progress reports.
    ///
    /// By default, this is invisible so that it isn't shown during tests, but
    /// it will be configured to be visible early during main.
    pub static ref MULTIPROGRESS: MultiProgress =
        MultiProgress::with_draw_target(ProgressDrawTarget::hidden());
}

/// Helper for bracketing some region with an indeterminate spinner which shows
/// no meaningful progress.
pub fn indeterminate_spinner(
    prefix: impl Into<Cow<'static, str>>,
    message: impl Into<Cow<'static, str>>,
) -> ProgressBar {
    let progress_bar = MULTIPROGRESS.add(
        ProgressBar::new_spinner()
            .with_style(
                ProgressStyle::with_template("{prefix:>12.cyan.bold} {msg} {spinner}").unwrap(),
            )
            .with_prefix(prefix)
            .with_message(message),
    );
    progress_bar.enable_steady_tick(Duration::from_millis(100));
    progress_bar
}

/// Create a new progress bar with a cargo-inspired style.
pub fn progress_bar(
    prefix: impl Into<Cow<'static, str>>,
    message: impl Into<Cow<'static, str>>,
    len: u64,
) -> ProgressBar {
    let progress_bar = MULTIPROGRESS.add(
        ProgressBar::new(len)
            .with_style(
                ProgressStyle::with_template("{prefix:>12.cyan.bold} {msg} [{bar:57}] {pos}/{len}")
                    .unwrap()
                    .progress_chars("=> "),
            )
            .with_prefix(prefix)
            .with_message(message),
    );
    progress_bar.tick();
    progress_bar
}

/// Helper guard object to increment progress for the given progress bar by the
/// given amount when this object is destroyed.
pub struct IncProgressOnDrop<'a>(pub &'a ProgressBar, pub u64);
impl Drop for IncProgressOnDrop<'_> {
    fn drop(&mut self) {
        self.0.inc(self.1);
    }
}

/// A helper type which implements `io::Write`, and will buffer up input, then
/// suspend the MultiProgress and write it all out when dropped to avoid
/// tearing.
///
/// This is used for tracing logs when no log file is specified.
pub struct StderrLogWriter {
    buffer: Vec<u8>,
}

impl StderrLogWriter {
    pub fn new() -> Self {
        StderrLogWriter { buffer: Vec::new() }
    }
}

impl io::Write for StderrLogWriter {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        io::Write::write(&mut self.buffer, buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        let buffer = mem::take(&mut self.buffer);
        MULTIPROGRESS.suspend(|| io::stderr().write_all(&buffer))
    }
}

impl Drop for StderrLogWriter {
    fn drop(&mut self) {
        let _ = io::Write::flush(self);
    }
}
