use std::io::Write;
use std::sync::Arc;
use crate::shared::csv::CsvOptions;
use crate::shared::datum::Duplicates;
use crate::shared::error::Fail;
use crate::shared::json::JsonOptions;
use crate::shared::limits::{AbortFlag, Limits, Metrics};
use crate::shared::route::{CaptureSpec, RouteSink};
use crate::shared::scan::Transition;
use crate::shared::sink::{Flow, Sink};
use crate::shared::table::{TableBinding, TableSink};
use crate::shared::text::{JoinOut, TextOut};
pub type ScanStep<V> = Box<dyn FnMut(V, V) -> Result<Transition<V, V>, Fail> + Send>;
pub type ScanFinish<V> = Box<dyn FnOnce(V) -> Result<Vec<V>, Fail> + Send>;
pub type ScanOut<V> = Box<dyn FnMut(V) -> Result<Flow, Fail> + Send>;
pub trait ScanEmitter<V>: Send {
fn item(&mut self, item: V) -> Result<Flow, Fail>;
fn finish(&mut self) -> Result<Flow, Fail>;
}
pub trait Routers<V>: Send + Sync {
fn router(
&self,
specs: Vec<CaptureSpec>,
limits: &Limits,
duplicates: Duplicates,
metrics: Arc<Metrics>,
downstream: Box<dyn RouteSink + Send>,
) -> Result<Box<dyn Sink + Send>, Fail>;
fn table_from_json(
&self,
binding: TableBinding,
limits: &Limits,
duplicates: Duplicates,
metrics: Arc<Metrics>,
sink: Box<dyn TableSink + Send>,
) -> Result<Box<dyn Sink + Send>, Fail>;
fn scan_emit(
&self,
initial: V,
step: ScanStep<V>,
finish: ScanFinish<V>,
out: ScanOut<V>,
) -> Box<dyn ScanEmitter<V>>;
fn guarded(
&self,
inner: Box<dyn Sink + Send>,
limits: &Limits,
abort: AbortFlag,
metrics: Arc<Metrics>,
) -> Box<dyn Sink + Send>;
}
pub trait Renderers: Send + Sync {
fn json(&self, out: Box<dyn TextOut + Send>, options: JsonOptions) -> Box<dyn Sink + Send>;
fn csv(
&self,
out: Box<dyn TextOut + Send>,
options: CsvOptions,
) -> Result<Box<dyn TableSink + Send>, Fail>;
fn records_to_json(&self, sink: Box<dyn Sink + Send>) -> Box<dyn TableSink + Send>;
fn join<'a>(
&self,
out: Box<dyn TextOut + Send + 'a>,
separator: &str,
) -> Box<dyn JoinOut + Send + 'a>;
fn replace_text<'a>(
&self,
out: Box<dyn TextOut + Send + 'a>,
from: &str,
to: &str,
) -> Box<dyn TextOut + Send + 'a>;
fn write_out(
&self,
writer: Box<dyn Write + Send>,
limits: &Limits,
metrics: Arc<Metrics>,
) -> Box<dyn TextOut + Send>;
}