use std::fmt;
use std::io;

#[derive(Debug)]
pub enum OLMError {
    Io(io::Error),
    Json(serde_json::Error),
    Mphf(String),
    InvalidLayer(String),
}

pub type OLMResult<T> = Result<T, OLMError>;

impl fmt::Display for OLMError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            OLMError::Io(e)            => write!(f, "I/O error: {e}"),
            OLMError::Json(e)          => write!(f, "JSON error: {e}"),
            OLMError::Mphf(s)          => write!(f, "MPHF error: {s}"),
            OLMError::InvalidLayer(s)  => write!(f, "invalid layer: {s}"),
        }
    }
}

impl std::error::Error for OLMError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            OLMError::Io(e)   => Some(e),
            OLMError::Json(e) => Some(e),
            _                 => None,
        }
    }
}

impl From<io::Error> for OLMError {
    fn from(e: io::Error) -> Self { OLMError::Io(e) }
}

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

impl From<obiskio::SKError> for OLMError {
    fn from(e: obiskio::SKError) -> Self {
        match e {
            obiskio::SKError::Io(io_err) => OLMError::Io(io_err),
            other => OLMError::InvalidLayer(other.to_string()),
        }
    }
}
