//! Various `prodash` types along with various utilities for comfort.
use std::io;

#[cfg(feature = "progress-unit-bytes")]
pub use bytesize;
pub use prodash::{
    self,
    messages::MessageLevel,
    progress::{
        AtomicStep, Discard, DoOrDiscard, Either, Id, Step, StepShared, Task, ThroughputOnDrop, Value, UNKNOWN,
    },
    unit, BoxedDynNestedProgress, Count, DynNestedProgress, DynNestedProgressToNestedProgress, NestedProgress,
    Progress, Unit,
};
/// A stub for the portions of the `bytesize` crate that we use internally in `gitoxide`.
#[cfg(not(feature = "progress-unit-bytes"))]
pub mod bytesize {
    /// A stub for the `ByteSize` wrapper.
    pub struct ByteSize(pub u64);

    impl std::fmt::Display for ByteSize {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            self.0.fmt(f)
        }
    }
}

/// A unit for displaying bytes with throughput and progress percentage.
#[cfg(feature = "progress-unit-bytes")]
pub fn bytes() -> Option<Unit> {
    Some(unit::dynamic_and_mode(
        unit::Bytes,
        unit::display::Mode::with_throughput().and_percentage(),
    ))
}

/// A unit for displaying bytes with throughput and progress percentage.
#[cfg(not(feature = "progress-unit-bytes"))]
pub fn bytes() -> Option<Unit> {
    Some(unit::label_and_mode(
        "B",
        unit::display::Mode::with_throughput().and_percentage(),
    ))
}

/// A unit for displaying human readable numbers with throughput and progress percentage, and a single decimal place.
pub fn count(name: &'static str) -> Option<Unit> {
    count_with_decimals(name, 1)
}

/// A unit for displaying human readable numbers with `name` suffix,
/// with throughput and progress percentage, and `decimals` decimal places.
#[cfg(feature = "progress-unit-human-numbers")]
pub fn count_with_decimals(name: &'static str, decimals: usize) -> Option<Unit> {
    Some(unit::dynamic_and_mode(
        unit::Human::new(
            {
                let mut f = unit::human::Formatter::new();
                f.with_decimals(decimals);
                f
            },
            name,
        ),
        unit::display::Mode::with_throughput().and_percentage(),
    ))
}

/// A unit for displaying human readable numbers with `name` suffix,
/// with throughput and progress percentage, and `decimals` decimal places.
#[cfg(not(feature = "progress-unit-human-numbers"))]
pub fn count_with_decimals(name: &'static str, _decimals: usize) -> Option<Unit> {
    Some(unit::label_and_mode(
        name,
        unit::display::Mode::with_throughput().and_percentage(),
    ))
}

/// A predefined unit for displaying a multi-step progress
pub fn steps() -> Option<Unit> {
    Some(unit::dynamic(unit::Range::new("steps")))
}

/// A structure passing every [`read`](std::io::Read::read()) call through to the contained Progress instance using [`inc_by(bytes_read)`](Count::inc_by()).
pub struct Read<T, P> {
    /// The implementor of [`std::io::Read`] to which progress is added
    pub inner: T,
    /// The progress instance receiving progress information on each invocation of `reader`
    pub progress: P,
}

impl<T, P> io::Read for Read<T, P>
where
    T: io::Read,
    P: Progress,
{
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let bytes_read = self.inner.read(buf)?;
        self.progress.inc_by(bytes_read);
        Ok(bytes_read)
    }
}

impl<T, P> io::BufRead for Read<T, P>
where
    T: io::BufRead,
    P: Progress,
{
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.inner.fill_buf()
    }

    fn consume(&mut self, amt: usize) {
        self.inner.consume(amt)
    }
}

/// A structure passing every [`write`][std::io::Write::write()] call through to the contained Progress instance using [`inc_by(bytes_written)`](Count::inc_by()).
///
/// This is particularly useful if the final size of the bytes to write is known or can be estimated precisely enough.
pub struct Write<T, P> {
    /// The implementor of [`std::io::Write`] to which progress is added
    pub inner: T,
    /// The progress instance receiving progress information on each invocation of `reader`
    pub progress: P,
}

impl<T, P> io::Write for Write<T, P>
where
    T: io::Write,
    P: Progress,
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let written = self.inner.write(buf)?;
        self.progress.inc_by(written);
        Ok(written)
    }

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

impl<T, P> io::Seek for Write<T, P>
where
    T: io::Seek,
{
    fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
        self.inner.seek(pos)
    }
}
