use bone_render::{OffscreenContext, RenderError, ViewportExtent, ViewportPx};

const ADAPTER_RETRIES: u32 = 3;
const ADAPTER_RETRY_BACKOFF_MS: u64 = 100;

#[must_use]
pub fn extent_square(side: u32) -> ViewportExtent {
    ViewportExtent::square(ViewportPx::new(side))
}

#[must_use]
pub fn make_context(extent: ViewportExtent) -> OffscreenContext {
    let mut last_err: Option<RenderError> = None;
    for attempt in 0..ADAPTER_RETRIES {
        match pollster::block_on(OffscreenContext::new(extent)) {
            Ok(ctx) => return ctx,
            Err(e @ (RenderError::NoAdapter(_) | RenderError::Device(_))) => {
                last_err = Some(e);
                let backoff_ms = ADAPTER_RETRY_BACKOFF_MS * u64::from(attempt + 1);
                std::thread::sleep(std::time::Duration::from_millis(backoff_ms));
            }
            Err(e) => panic!("offscreen context init failed: {e}"),
        }
    }
    match last_err {
        Some(RenderError::NoAdapter(e)) => panic!(
            "no wgpu adapter available after {ADAPTER_RETRIES} attempts, configure lavapipe or an iGPU: {e}"
        ),
        Some(RenderError::Device(e)) => {
            panic!("wgpu device request failed after {ADAPTER_RETRIES} attempts: {e}")
        }
        Some(other) => {
            panic!("offscreen context init failed after {ADAPTER_RETRIES} attempts: {other}")
        }
        None => unreachable!("retry loop always populates last_err on failure"),
    }
}
