use wasm_bindgen::prelude::*;
use std::sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
};
#[wasm_bindgen]
pub struct Aborted;
impl std::error::Error for Aborted {}
impl std::fmt::Debug for Aborted {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "task aborted")
    }
}
impl std::fmt::Display for Aborted {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "task aborted")
    }
}
#[derive(Default, Clone)]
#[wasm_bindgen]
pub struct Abortable(Arc<AtomicBool>);
#[wasm_bindgen]
impl Abortable {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Self {
        Self(Arc::new(AtomicBool::new(false)))
    }
    #[inline]
    #[wasm_bindgen(js_name=isAborted)]
    pub fn is_aborted(&self) -> bool {
        self.0.load(Ordering::SeqCst)
    }
    #[inline]
    pub fn abort(&self) {
        self.0.store(true, Ordering::SeqCst);
    }
    #[inline]
    pub fn check(&self) -> Result<(), Aborted> {
        if self.is_aborted() {
            Err(Aborted)
        } else {
            Ok(())
        }
    }
    #[inline]
    pub fn reset(&self) {
        self.0.store(false, Ordering::SeqCst);
    }
}
impl TryFrom<&JsValue> for Abortable {
    type Error = JsValue;
    fn try_from(value: &JsValue) -> Result<Self, Self::Error> {
        use wasm_bindgen::convert::*;
        let idx = IntoWasmAbi::into_abi(value);
        #[link(wasm_import_module = "__wbindgen_placeholder__")]
        #[cfg(all(
            target_arch = "wasm32",
            not(any(target_os = "emscripten", target_os = "wasi"))
        ))]
        extern "C" {
            fn __wbg_abortable_unwrap(ptr: u32) -> u32;
        }
        #[cfg(not(all(
            target_arch = "wasm32",
            not(any(target_os = "emscripten", target_os = "wasi"))
        )))]
        unsafe fn __wbg_abortable_unwrap(_: u32) -> u32 {
            panic!("cannot convert from JsValue outside of the wasm target")
        }
        let ptr = unsafe { __wbg_abortable_unwrap(idx) };
        if ptr == 0 {
            wasm_bindgen::__rt::std::result::Result::Err(value.clone())
        } else {
            unsafe {
                wasm_bindgen::__rt::std::result::Result::Ok(
                    <Self as FromWasmAbi>::from_abi(ptr).clone(),
                )
            }
        }
    }
}