use futures::future::join_all;
use tokio::task::JoinHandle;

use crate::chopper::error::Result;
use crate::cli::config::Config;
use crate::driver::util::header::get_header_from_sources;
use crate::driver::util::sink::drive_output_with_factory;
use crate::driver::util::source::{drive_sources, inputs_to_sources_with_factory};

pub async fn drive(config: Config) -> Result<()> {
    let inputs = config.inputs;
    let output = config.output;
    let input_factory = config.input_factory;
    let output_factory = config.output_factory;
    let timestamp_range = config.timestamp_range;

    let sources = inputs_to_sources_with_factory(&input_factory, &inputs, &timestamp_range)?;
    let header = get_header_from_sources(&sources)?;

    let mut drivers: Vec<JoinHandle<()>> = Vec::new();

    let (output_tx, output_handle) =
        drive_output_with_factory(&output_factory, &output, header).await?;
    drivers.push(output_handle);

    drivers.append(
        drive_sources(sources, output_tx, timestamp_range)
            .await
            .as_mut(),
    );

    join_all(drivers).await;
    Ok(())
}
