//! Implementation for `miniz_oxide` rust backend.

use std::convert::TryInto;
use std::fmt;

use miniz_oxide::deflate::core::CompressorOxide;
use miniz_oxide::inflate::stream::InflateState;
pub use miniz_oxide::*;

pub const MZ_NO_FLUSH: isize = MZFlush::None as isize;
pub const MZ_PARTIAL_FLUSH: isize = MZFlush::Partial as isize;
pub const MZ_SYNC_FLUSH: isize = MZFlush::Sync as isize;
pub const MZ_FULL_FLUSH: isize = MZFlush::Full as isize;
pub const MZ_FINISH: isize = MZFlush::Finish as isize;

use super::*;
use crate::mem;

// miniz_oxide doesn't provide any error messages (yet?)
#[derive(Default)]
pub struct ErrorMessage;

impl ErrorMessage {
    pub fn get(&self) -> Option<&str> {
        None
    }
}

fn format_from_bool(zlib_header: bool) -> DataFormat {
    if zlib_header {
        DataFormat::Zlib
    } else {
        DataFormat::Raw
    }
}

pub struct Inflate {
    inner: Box<InflateState>,
    total_in: u64,
    total_out: u64,
}

impl fmt::Debug for Inflate {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(
            f,
            "miniz_oxide inflate internal state. total_in: {}, total_out: {}",
            self.total_in, self.total_out,
        )
    }
}

impl InflateBackend for Inflate {
    fn make(zlib_header: bool, _window_bits: u8) -> Self {
        let format = format_from_bool(zlib_header);

        Inflate {
            inner: InflateState::new_boxed(format),
            total_in: 0,
            total_out: 0,
        }
    }

    fn decompress(
        &mut self,
        input: &[u8],
        output: &mut [u8],
        flush: FlushDecompress,
    ) -> Result<Status, DecompressError> {
        let flush = MZFlush::new(flush as i32).unwrap();

        let res = inflate::stream::inflate(&mut self.inner, input, output, flush);
        self.total_in += res.bytes_consumed as u64;
        self.total_out += res.bytes_written as u64;

        match res.status {
            Ok(status) => match status {
                MZStatus::Ok => Ok(Status::Ok),
                MZStatus::StreamEnd => Ok(Status::StreamEnd),
                MZStatus::NeedDict => {
                    mem::decompress_need_dict(self.inner.decompressor().adler32().unwrap_or(0))
                }
            },
            Err(status) => match status {
                MZError::Buf => Ok(Status::BufError),
                _ => mem::decompress_failed(ErrorMessage),
            },
        }
    }

    fn reset(&mut self, zlib_header: bool) {
        self.inner.reset(format_from_bool(zlib_header));
        self.total_in = 0;
        self.total_out = 0;
    }
}

impl Backend for Inflate {
    #[inline]
    fn total_in(&self) -> u64 {
        self.total_in
    }

    #[inline]
    fn total_out(&self) -> u64 {
        self.total_out
    }
}

pub struct Deflate {
    inner: Box<CompressorOxide>,
    total_in: u64,
    total_out: u64,
}

impl fmt::Debug for Deflate {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(
            f,
            "miniz_oxide deflate internal state. total_in: {}, total_out: {}",
            self.total_in, self.total_out,
        )
    }
}

impl DeflateBackend for Deflate {
    fn make(level: Compression, zlib_header: bool, _window_bits: u8) -> Self {
        // Check in case the integer value changes at some point.
        debug_assert!(level.level() <= 10);

        let mut inner: Box<CompressorOxide> = Box::default();
        let format = format_from_bool(zlib_header);
        inner.set_format_and_level(format, level.level().try_into().unwrap_or(1));

        Deflate {
            inner,
            total_in: 0,
            total_out: 0,
        }
    }

    fn compress(
        &mut self,
        input: &[u8],
        output: &mut [u8],
        flush: FlushCompress,
    ) -> Result<Status, CompressError> {
        let flush = MZFlush::new(flush as i32).unwrap();
        let res = deflate::stream::deflate(&mut self.inner, input, output, flush);
        self.total_in += res.bytes_consumed as u64;
        self.total_out += res.bytes_written as u64;

        match res.status {
            Ok(status) => match status {
                MZStatus::Ok => Ok(Status::Ok),
                MZStatus::StreamEnd => Ok(Status::StreamEnd),
                MZStatus::NeedDict => mem::compress_failed(ErrorMessage),
            },
            Err(status) => match status {
                MZError::Buf => Ok(Status::BufError),
                _ => mem::compress_failed(ErrorMessage),
            },
        }
    }

    fn reset(&mut self) {
        self.total_in = 0;
        self.total_out = 0;
        self.inner.reset();
    }
}

impl Backend for Deflate {
    #[inline]
    fn total_in(&self) -> u64 {
        self.total_in
    }

    #[inline]
    fn total_out(&self) -> u64 {
        self.total_out
    }
}
