//! Errors that can occur when working with IndexedDB.

use std::fmt;
use wasm_bindgen::JsValue;

/// An error that occurred when working with IndexedDB.
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
    /// Accessing a Window has failed.
    WindowNotAvailable,
    /// IndexedDB is not supported by your browser.
    NotSupported(String),
    /// The database returned a generic error.
    Generic(String),
    /// The operation was canceled
    Canceled,
}

impl From<std::io::Error> for Error {
    fn from(other: std::io::Error) -> Self {
        Self::Generic(other.to_string())
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::WindowNotAvailable => "Accessing a Window has failed",
            Error::NotSupported(_) => "IndexedDB is not supported by your browser",
            Error::Generic(_) => "The database returned a generic error",
            Error::Canceled => "The operation was canceled",
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Error::WindowNotAvailable => write!(f, "Accessing a Window has failed"),
            Error::NotSupported(ref err) => {
                write!(f, "IndexedDB is not supported by your browser: {}", err,)
            }
            Error::Generic(ref err) => {
                write!(f, "Generic error: {}", err,)
            }
            Error::Canceled => write!(f, "The operation was canceled"),
        }
    }
}

pub(crate) fn io_err_string<T: ToString>(e: T) -> std::io::Error {
    std::io::Error::other(e.to_string())
}

pub(crate) fn io_err_jsvalue(e: JsValue) -> std::io::Error {
    std::io::Error::other(e.as_string().unwrap_or_default())
}

pub(crate) fn bad_cast_io_err(context: &str, v: JsValue) -> std::io::Error {
    io_err_string(format!("{} is a {:?}", context, v))
}
pub(crate) fn bad_cast_generic(context: &str, v: JsValue) -> Error {
    Error::Generic(format!("{} is a {:?}", context, v))
}
