//! Split files into chunks.

use std::{fs::File, path::PathBuf};

use clap::Parser;

use obnam::chunk_splitter::{ChunkSplitter, SplitMethod, SplitterError};

use super::{Args, Leaf, ObnamError};

/// List the chunks a file would be split to by a backup run.
#[derive(Debug, Parser)]
pub struct List {
    /// How should file be split into chunks?
    method: SplitMethod,

    /// Name of file.
    filename: PathBuf,
}

impl Leaf for List {
    type Error = SplitCmdError;
    fn run(&self, _args: &Args, _config: &obnam::config::Config) -> Result<(), Self::Error> {
        let file = File::open(&self.filename)
            .map_err(|err| SplitCmdError::Open(self.filename.clone(), err))?;
        let splitter = ChunkSplitter::new(self.method, file);
        let mut offset = 0;
        for chunk in splitter {
            let chunk = chunk.map_err(SplitCmdError::ReadChunk)?;
            println!("offset {}, length {}", offset, chunk.len());
            offset += chunk.len();
        }
        Ok(())
    }
}

/// Errors from `obnam split`.
#[derive(Debug, thiserror::Error)]
pub enum SplitCmdError {
    /// Can't open file for reading.
    #[error("failed to open file for reading: {0}")]
    Open(PathBuf, #[source] std::io::Error),

    /// Can't read chunk.
    #[error("failed to read chunk")]
    ReadChunk(#[source] SplitterError),
}

impl From<SplitCmdError> for ObnamError {
    fn from(err: SplitCmdError) -> Self {
        Self::Split(err)
    }
}
