use color_eyre::eyre::{OptionExt, Result};
use crate::action::{Action, ActionWrapper};
use crate::filter::{Filter, FilterWrapper};
use crate::generator::{GenWrapper, Generator};
use crate::launcher::batcher::Batcher;
use crate::sorter::{Sorter, SorterWrapper};
use crate::source::{Source, transform_source};
use crate::ui::UI;
pub mod batcher;
pub struct Launcher<'a, Cushion, UIT, UIContext>
where
UIT: UI<'a, Context = UIContext>,
UIContext: 'a + Send,
Cushion: 'a + Sync,
{
batcher: Batcher<'a, Cushion, UIContext>,
actions: Vec<Box<dyn Action<'a, Context = Cushion>>>,
ui: Option<UIT>,
}
impl<'a, Cushion, UIT, UIContext> Default for Launcher<'a, Cushion, UIT, UIContext>
where
UIT: UI<'a, Context = UIContext> + 'a,
UIContext: 'a + Send,
Cushion: 'a + Sync,
{
fn default() -> Self {
Self {
batcher: batcher::Batcher::default(),
actions: vec![],
ui: None,
}
}
}
impl<'a, Cushion, UIT, UIContext> Launcher<'a, Cushion, UIT, UIContext>
where
UIT: UI<'a, Context = UIContext> + Sync + 'a,
UIContext: 'a + Send,
Cushion: 'a + Send + Sync,
{
pub fn add_source<SourceContext, F>(
self,
source: Source<'a, SourceContext>,
transformer: F,
) -> Self
where
F: Fn(SourceContext) -> Cushion + Send + 'a,
SourceContext: 'a,
{
self.add_raw_source(transform_source(source, transformer))
}
pub fn add_raw_source(mut self, source: Source<'a, Cushion>) -> Self {
self.batcher.add_raw_source(source);
self
}
pub fn add_filter<FilterContext, FilterT, F>(self, filter: FilterT, transformer: F) -> Self
where
F: Fn(&Cushion) -> FilterContext + Send + 'a,
FilterContext: 'a + Sync,
FilterT: Filter<'a, Context = FilterContext> + 'a,
{
self.add_raw_filter(FilterWrapper::new(filter, transformer))
}
pub fn add_raw_filter<FilterT>(mut self, filter: FilterT) -> Self
where
FilterT: Filter<'a, Context = Cushion> + 'a,
{
self.batcher.add_raw_filter(filter);
self
}
pub fn add_sorter<SorterContext, SorterT, F>(self, sorter: SorterT, transformer: F) -> Self
where
F: Fn(&Cushion) -> SorterContext + Send + 'a,
SorterContext: 'a + Sync,
SorterT: Sorter<'a, Context = SorterContext> + 'a,
Cushion: 'a + Send,
{
self.add_raw_sorter(SorterWrapper::new(sorter, transformer))
}
pub fn add_raw_sorter<SorterT>(mut self, sorter: SorterT) -> Self
where
SorterT: Sorter<'a, Context = Cushion> + 'a,
{
self.batcher.add_raw_sorter(sorter);
self
}
pub fn add_action<ActionContext, ActionT, F>(self, action: ActionT, transformer: F) -> Self
where
F: Fn(&Cushion) -> ActionContext + Send + 'a,
ActionT: Action<'a, Context = ActionContext> + 'a,
ActionContext: 'a,
Cushion: 'a + Sync,
{
self.add_raw_action(ActionWrapper::new(action, transformer))
}
pub fn add_raw_action<ActionT>(mut self, action: ActionT) -> Self
where
ActionT: Action<'a, Context = Cushion> + 'a,
{
self.actions.push(Box::new(action));
self
}
pub fn set_ui<F>(mut self, ui: UIT, transformer: F) -> Self
where
F: Fn(&Cushion) -> UIContext + Send + Sync + 'a,
{
self.ui = Some(ui);
self.batcher.cusion_to_ui = Some(Box::new(transformer));
self
}
pub fn add_generator<Item, GenT, F>(self, generator: GenT, transformer: F) -> Self
where
Item: 'a,
F: Fn(Item) -> Cushion + Sync + Send + 'a,
GenT: Generator<Item = Item> + Sync + Send + 'a,
Cushion: Sync + 'a,
{
self.add_raw_generator(GenWrapper::new(generator, transformer))
}
pub fn add_raw_generator<GenT>(mut self, generator: GenT) -> Self
where
GenT: Generator<Item = Cushion> + Sync + Send + 'a,
{
self.batcher.add_raw_generator(generator);
self
}
pub async fn run(self) -> Result<()> {
let cusion: Option<Cushion> = self
.ui
.ok_or_eyre("UI must be set before calling run")?
.run(self.batcher)
.await?;
if let Some(cusion) = cusion {
for ai in self.actions {
ai.act(&cusion)?;
}
}
Ok(())
}
pub fn filter_and(mut self, flag: bool) -> Self {
self.batcher.filter_and = flag;
self
}
pub fn batch_size(mut self, batch_size: usize) -> Self {
self.batcher.batch_size = batch_size;
self
}
}