use vdir::transport::dir::dir_transport::DirTransport;
use vfile::util::location::Location;

use crate::chopper::error::Result;
use crate::chopper::types::TimestampRange;
use crate::input::dir::dir_location_provider::DirLocationProvider;
use crate::input::dir::factory::DirInputFactory;
use crate::input::input::InputFormat;
use crate::input::location::factory::ChopperLocationInputFactory;
use crate::source::multi_source::MultiSource;
use crate::source::source::Source;

pub struct SourceDirInputFactory {
    loc_input_factory: ChopperLocationInputFactory,
    dir_transports: Vec<Box<dyn DirTransport>>,
}

impl SourceDirInputFactory {
    pub fn new(
        loc_input_factory: ChopperLocationInputFactory,
        dir_transports: Vec<Box<dyn DirTransport>>,
    ) -> SourceDirInputFactory {
        SourceDirInputFactory {
            loc_input_factory,
            dir_transports,
        }
    }
}

impl DirInputFactory<Box<dyn Source>> for SourceDirInputFactory {
    fn create_source(
        &self,
        loc: &Location,
        range: &TimestampRange,
        input_format: InputFormat,
    ) -> Result<Option<Box<dyn Source>>> {
        for transport in &self.dir_transports {
            if !transport.can_handle(loc) {
                continue;
            }

            let provider = Box::new(DirLocationProvider::new(transport, loc)?);
            let source = MultiSource::new(
                self.loc_input_factory.clone(),
                provider,
                *range,
                input_format,
                None,
            )?;
            return Ok(Some(Box::new(source)));
        }

        Ok(None)
    }
}
