use std::future::Future;
use std::ops::Range;
use std::pin::Pin;
use vantage_core::Result;
use crate::dio::Dio;
use crate::lens::chunk_sink::ChunkSink;
use crate::ops::{ChangeEvent, QueryDescriptor, WriteOp};
pub type DioCallbackFuture<'a> = Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
pub type DioCallback =
Box<dyn for<'a> Fn(&'a Dio) -> DioCallbackFuture<'a> + Send + Sync + 'static>;
pub type DioWriteCallback =
Box<dyn for<'a> Fn(&'a Dio, WriteOp) -> DioCallbackFuture<'a> + Send + Sync + 'static>;
pub type DioEventCallback =
Box<dyn for<'a> Fn(&'a Dio, ChangeEvent) -> DioCallbackFuture<'a> + Send + Sync + 'static>;
pub type DioQueryCallback =
Box<dyn for<'a> Fn(&'a Dio, QueryDescriptor) -> DioCallbackFuture<'a> + Send + Sync + 'static>;
pub type DioTotalProviderFuture<'a> = Pin<Box<dyn Future<Output = Result<usize>> + Send + 'a>>;
pub type DioTotalProviderCallback =
Box<dyn for<'a> Fn(&'a Dio) -> DioTotalProviderFuture<'a> + Send + Sync + 'static>;
pub type DioLoadChunkCallback = Box<
dyn for<'a> Fn(&'a Dio, Range<usize>, ChunkSink) -> DioCallbackFuture<'a>
+ Send
+ Sync
+ 'static,
>;
#[derive(Default)]
pub struct LensCallbacks {
pub on_start: Option<DioCallback>,
pub on_refresh: Option<DioCallback>,
pub on_write: Option<DioWriteCallback>,
pub on_event: Option<DioEventCallback>,
pub on_query: Option<DioQueryCallback>,
pub total_provider: Option<DioTotalProviderCallback>,
pub on_load_chunk: Option<DioLoadChunkCallback>,
}
pub fn boxed_dio_callback<F, Fut>(f: F) -> DioCallback
where
F: for<'a> Fn(&'a Dio) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<()>> + Send + 'static,
{
Box::new(move |dio| Box::pin(f(dio)))
}
pub fn boxed_dio_write_callback<F, Fut>(f: F) -> DioWriteCallback
where
F: for<'a> Fn(&'a Dio, WriteOp) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<()>> + Send + 'static,
{
Box::new(move |dio, op| Box::pin(f(dio, op)))
}
pub fn boxed_dio_event_callback<F, Fut>(f: F) -> DioEventCallback
where
F: for<'a> Fn(&'a Dio, ChangeEvent) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<()>> + Send + 'static,
{
Box::new(move |dio, ev| Box::pin(f(dio, ev)))
}
pub fn boxed_dio_query_callback<F, Fut>(f: F) -> DioQueryCallback
where
F: for<'a> Fn(&'a Dio, QueryDescriptor) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<()>> + Send + 'static,
{
Box::new(move |dio, q| Box::pin(f(dio, q)))
}
pub fn boxed_total_provider_callback<F, Fut>(f: F) -> DioTotalProviderCallback
where
F: for<'a> Fn(&'a Dio) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<usize>> + Send + 'static,
{
Box::new(move |dio| Box::pin(f(dio)))
}
pub fn boxed_load_chunk_callback<F, Fut>(f: F) -> DioLoadChunkCallback
where
F: for<'a> Fn(&'a Dio, Range<usize>, ChunkSink) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<()>> + Send + 'static,
{
Box::new(move |dio, range, sink| Box::pin(f(dio, range, sink)))
}