use std::future::Future;
use std::pin::Pin;
use std::sync::atomic::{AtomicUsize, Ordering};
use crate::core::Result;
use once_cell::sync::Lazy;
use parking_lot::RwLock;
use super::request::FlowRequest;
pub type MiddlewareFuture = Pin<Box<dyn Future<Output = Result<FlowRequest>> + Send>>;
pub type MiddlewareFn = fn(FlowRequest) -> MiddlewareFuture;
static ORDER: AtomicUsize = AtomicUsize::new(0);
static MIDDLEWARE: Lazy<RwLock<Vec<(usize, MiddlewareFn)>>> = Lazy::new(|| RwLock::new(Vec::new()));
pub fn register_middleware(f: MiddlewareFn) {
let order = ORDER.fetch_add(1, Ordering::SeqCst);
MIDDLEWARE.write().push((order, f));
MIDDLEWARE.write().sort_by_key(|(o, _)| *o);
}
pub async fn run_middleware(req: FlowRequest) -> Result<FlowRequest> {
let chain: Vec<MiddlewareFn> = MIDDLEWARE.read().iter().map(|(_, f)| *f).collect();
let mut current = req;
for mw in chain {
current = mw(current).await?;
}
Ok(current)
}