use std::io::Read;
use bytes::BytesMut;
use crate::{
    v2::read::{
        decoder::{DecodeError, Decoder},
        Section,
    },
    DetectError, Version,
};
const DEFAULT_READ_SIZE: usize = 4 * 1024;
#[derive(Debug)]
pub struct StreamingReader<R> {
    inner: R,
    buffer: BytesMut,
}
impl<R: Read> StreamingReader<R> {
    pub fn new(mut reader: R) -> Result<Self, StreamingReaderError> {
        let version = crate::detect(&mut reader)?;
        if version != Version::V2 {
            return Err(StreamingReaderError::UnsupportedVersion(version));
        }
        Ok(StreamingReader {
            inner: reader,
            buffer: BytesMut::new(),
        })
    }
    pub fn sections(mut self) -> impl Iterator<Item = Result<Section, StreamingReaderError>> {
        std::iter::from_fn(move || self.next_section().transpose())
    }
    pub fn next_section(&mut self) -> Result<Option<Section>, StreamingReaderError> {
        loop {
            let bytes_read = self.fill_buffer()?;
            match Decoder.decode(&mut self.buffer)? {
                Some(section) => return Ok(Some(section)),
                None if bytes_read != 0 => {
                    }
                None => return Ok(None),
            }
        }
    }
    fn fill_buffer(&mut self) -> Result<usize, std::io::Error> {
        let original_length = self.buffer.len();
        self.buffer.resize(original_length + DEFAULT_READ_SIZE, 0);
        let scratch_space = &mut self.buffer[original_length..];
        let bytes_read = self.inner.read(scratch_space)?;
        self.buffer.truncate(original_length + bytes_read);
        Ok(bytes_read)
    }
}
#[derive(Debug, thiserror::Error)]
pub enum StreamingReaderError {
    #[error(transparent)]
    Io(#[from] std::io::Error),
    #[error("Unable to detect the WEBC version")]
    Detect(#[from] DetectError),
    #[error("The version, {_0}, isn't supported")]
    UnsupportedVersion(Version),
    #[error("Decode failed")]
    Decode(#[from] DecodeError),
}