#[cfg(feature = "zstd")]
use anyhow::Result;
#[cfg(feature = "zstd")]
use log::*;
#[cfg(feature = "zstd")]
use std::io::Write;

#[cfg(feature = "zstd")]
use std::fs::File;
#[cfg(feature = "zstd")]
use std::io::Read;
#[cfg(feature = "zstd")]
use std::path::PathBuf;
#[cfg(feature = "zstd")]
use zstd::stream::read::Decoder;
#[cfg(feature = "zstd")]
use zstd::stream::write::Encoder;

#[cfg(feature = "zstd")]
use crate::compression_engine::CompressionEngine;

#[cfg(feature = "zstd")]
#[derive(Debug, Eq, PartialEq, Clone, Default)]
pub struct CompressionEngineZstd {}

#[cfg(feature = "zstd")]
impl CompressionEngineZstd {
    pub fn new() -> CompressionEngineZstd {
        CompressionEngineZstd {}
    }
}

#[cfg(feature = "zstd")]
impl CompressionEngine for CompressionEngineZstd {
    fn open(&self, file_path: PathBuf) -> Result<Box<dyn Read + Send>> {
        debug!("COMPRESSION: Opening {:?} using {:?}", file_path, *self);

        let file = File::open(file_path)?;
        Ok(Box::new(Decoder::new(file)?))
    }

    fn create(&self, file_path: PathBuf) -> Result<Box<dyn Write>> {
        debug!("COMPRESSION: Writing to {:?} using {:?}", file_path, *self);

        let file = File::create(file_path)?;
        let zstd_write = Encoder::new(file, 3)?.auto_finish();

        Ok(Box::new(zstd_write))
    }

    fn clone_box(&self) -> Box<dyn CompressionEngine> {
        Box::new(self.clone())
    }
}
