use std::time::{Duration, Instant};

use dope_core::driver::{CompletionBackend, DriverLifecycle, PoolDriver};
use dope_futures::conn::Conn;
use dope_transport::Transport;

pub struct Drive;

impl Drive {
    pub fn until<T, B, F>(
        conn: &mut Conn<T, B>,
        driver: &mut B::Driver,
        timeout: Duration,
        mut done: F,
    ) where
        T: Transport,
        B: PoolDriver,
        F: FnMut(&mut Conn<T, B>) -> bool,
    {
        let deadline = Instant::now() + timeout;
        while !done(conn) {
            assert!(
                Instant::now() < deadline,
                "Drive::until: deadline exceeded; state={:?}",
                conn.state()
            );
            B::dispatch_completions(driver, conn);
            conn.drive(driver);
            let _ = driver.submit_only();
            let _ = driver.park_for(Duration::from_millis(10));
        }
    }
}
