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<Cushion, UIT, UIContext>
where
UIT: UI<Cushion, Context = UIContext>,
UIContext: Send,
Cushion: Sync + Send + 'static,
{
batcher: Batcher<Cushion, UIContext>,
actions: Vec<Box<dyn Action<Context = Cushion>>>,
ui: Option<UIT>,
}
impl<Cushion, UIT, UIContext> Default for Launcher<Cushion, UIT, UIContext>
where
UIT: UI<Cushion, Context = UIContext>,
UIContext: Send,
Cushion: Sync + Send,
{
fn default() -> Self {
Self {
batcher: batcher::Batcher::default(),
actions: vec![],
ui: None,
}
}
}
impl<Cushion, UIT, UIContext> Launcher<Cushion, UIT, UIContext>
where
UIT: UI<Cushion, Context = UIContext>,
UIContext: Send,
Cushion: Send + Sync + 'static,
{
pub fn add_source<SourceContext, F>(self, source: Source<SourceContext>, transformer: F) -> Self
where
F: Fn(SourceContext) -> Cushion + Send + 'static,
SourceContext: 'static,
{
self.add_raw_source(transform_source(source, transformer))
}
pub fn add_raw_source(mut self, source: Source<Cushion>) -> Self {
self.batcher.add_raw_source(source);
self
}
pub fn add_filter<FilterContext, FilterT, F>(self, filter: FilterT, transformer: F) -> Self
where
FilterT: Filter<Context = FilterContext> + 'static,
FilterContext: Sync + Send + 'static,
F: Fn(&Cushion) -> FilterContext + Send + 'static,
{
self.add_raw_filter(FilterWrapper::new(filter, transformer))
}
pub fn add_raw_filter<FilterT>(mut self, filter: FilterT) -> Self
where
FilterT: Filter<Context = Cushion> + 'static,
{
self.batcher.add_raw_filter(filter);
self
}
pub fn add_sorter<SorterContext, SorterT, F>(self, sorter: SorterT, transformer: F) -> Self
where
SorterT: Sorter<Context = SorterContext> + 'static,
SorterContext: Sync + Send + 'static,
F: Fn(&Cushion) -> SorterContext + Send + 'static,
{
self.add_raw_sorter(SorterWrapper::new(sorter, transformer))
}
pub fn add_raw_sorter<SorterT>(mut self, sorter: SorterT) -> Self
where
SorterT: Sorter<Context = Cushion> + 'static,
{
self.batcher.add_raw_sorter(sorter);
self
}
pub fn add_action<ActionContext: 'static, ActionT, F>(
self,
action: ActionT,
transformer: F,
) -> Self
where
ActionT: Action<Context = ActionContext> + 'static,
F: Fn(&Cushion) -> ActionContext + Send + 'static,
{
self.add_raw_action(ActionWrapper::new(action, transformer))
}
pub fn add_raw_action<ActionT>(mut self, action: ActionT) -> Self
where
ActionT: Action<Context = Cushion> + 'static,
{
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 + 'static,
{
self.ui = Some(ui);
self.batcher.cushion_to_ui = Some(Box::new(transformer));
self
}
pub fn add_generator<Item, GenT, F>(self, generator: GenT, transformer: F) -> Self
where
GenT: Generator<Item = Item> + Sync + Send + 'static,
Item: 'static,
F: Fn(Item) -> Cushion + Sync + Send + 'static,
{
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 + 'static,
{
self.batcher.add_raw_generator(generator);
self
}
pub async fn run(self) -> Result<()> {
let cushion: Option<Cushion> = self
.ui
.ok_or_eyre("UI must be set before calling run")?
.run(self.batcher)
.await?;
if let Some(cushion) = cushion {
for ai in self.actions {
ai.act(&cushion)?;
}
}
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
}
}