pub type Result<T> = std::result::Result<T, BioLibError>;

#[derive(Debug)]
pub enum BioLibError {
    Http { status: u16, message: String },
    Request(String),
    Json(serde_json::Error),
    Io(std::io::Error),
    BinaryFormat(String),
    AuthRequired(String),
    NotFound(String),
    PermissionDenied(String),
    Validation(String),
    CloudJobError(String),
    CloudJobFinished,
    WaitTimeout(String),
    General(String),
}

impl std::fmt::Display for BioLibError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Http { status, message } => write!(f, "HTTP error {status}: {message}"),
            Self::Request(err) => write!(f, "Request failed: {err}"),
            Self::Json(err) => write!(f, "JSON error: {err}"),
            Self::Io(err) => write!(f, "IO error: {err}"),
            Self::BinaryFormat(msg) => write!(f, "Binary format error: {msg}"),
            Self::AuthRequired(msg) => write!(f, "Authentication required: {msg}"),
            Self::NotFound(msg) => write!(f, "Not found: {msg}"),
            Self::PermissionDenied(msg) => write!(f, "Permission denied: {msg}"),
            Self::Validation(msg) => write!(f, "Validation error: {msg}"),
            Self::CloudJobError(msg) => write!(f, "Cloud job error: {msg}"),
            Self::CloudJobFinished => write!(f, "Cloud job already finished"),
            Self::WaitTimeout(msg) => write!(f, "{msg}"),
            Self::General(msg) => write!(f, "{msg}"),
        }
    }
}

impl std::error::Error for BioLibError {}

impl From<serde_json::Error> for BioLibError {
    fn from(err: serde_json::Error) -> Self {
        Self::Json(err)
    }
}

impl From<std::io::Error> for BioLibError {
    fn from(err: std::io::Error) -> Self {
        Self::Io(err)
    }
}
