use std::error::Error;
use std::fmt;
use std::fmt::Debug;
pub(crate) fn handle_fatal_error<E>(error: E)
where
    E: Debug,
{
    unreachable!("Encountered fatal error: {:?}", error);
}
pub(crate) fn olm_error() -> usize {
    unsafe { olm_sys::olm_error() }
}
static BAD_ACCOUNT_KEY: &str = "The supplied account key is invalid";
static INVALID_BASE64: &str = "The input base64 was invalid";
static BAD_MSG_KEY_ID: &str = "The message references an unknown key id";
static BAD_MSG_FMT: &str = "The message couldn't be decoded";
static BAD_MSG_MAC: &str = "The message couldn't be decrypted";
static BAD_MSG_VERSION: &str = "The message version is unsupported";
static BAD_SESSION_KEY: &str = "Can't initialise the inbound group session, invalid session key";
static BAD_MSG_INDEX: &str =
    "Can't decode the message, message index is earlier than our earliest known session key";
static NOT_ENOUGH_RAND: &str = "Not enough entropy was supplied";
static BUFFER_SMALL: &str = "Supplied output buffer is too small";
static INPUT_BUFFER_SMALL: &str = "Supplied input buffer is too small";
static UNKNOWN: &str = "An unknown error occured.";
#[derive(Debug, PartialEq)]
pub enum OlmAccountError {
    BadAccountKey,
    BadMessageKeyId,
    InvalidBase64,
    NotEnoughRandom,
    OutputBufferTooSmall,
    Unknown,
}
impl fmt::Display for OlmAccountError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let message = match self {
            OlmAccountError::BadAccountKey => BAD_ACCOUNT_KEY,
            OlmAccountError::BadMessageKeyId => BAD_MSG_KEY_ID,
            OlmAccountError::InvalidBase64 => INVALID_BASE64,
            OlmAccountError::NotEnoughRandom => NOT_ENOUGH_RAND,
            OlmAccountError::OutputBufferTooSmall => BUFFER_SMALL,
            OlmAccountError::Unknown => UNKNOWN,
        };
        write!(f, "{}", message)
    }
}
impl Error for OlmAccountError {}
impl Error for OlmSessionError {}
impl Error for OlmGroupSessionError {}
#[derive(Debug, PartialEq)]
pub enum OlmUtilityError {
    InvalidBase64,
    OutputBufferTooSmall,
    BadMessageMac,
    Unknown,
}
#[derive(Debug, PartialEq)]
pub enum OlmSessionError {
    BadAccountKey,
    BadMessageFormat,
    BadMessageKeyId,
    BadMessageMac,
    BadMessageVersion,
    InvalidBase64,
    NotEnoughRandom,
    OutputBufferTooSmall,
    Unknown,
}
impl fmt::Display for OlmSessionError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let message = match self {
            OlmSessionError::BadAccountKey => BAD_ACCOUNT_KEY,
            OlmSessionError::BadMessageKeyId => BAD_MSG_KEY_ID,
            OlmSessionError::BadMessageFormat => BAD_MSG_FMT,
            OlmSessionError::BadMessageMac => BAD_MSG_MAC,
            OlmSessionError::BadMessageVersion => BAD_MSG_VERSION,
            OlmSessionError::InvalidBase64 => INVALID_BASE64,
            OlmSessionError::NotEnoughRandom => NOT_ENOUGH_RAND,
            OlmSessionError::OutputBufferTooSmall => BUFFER_SMALL,
            OlmSessionError::Unknown => UNKNOWN,
        };
        write!(f, "{}", message)
    }
}
#[derive(Debug, PartialEq)]
pub enum OlmGroupSessionError {
    BadAccountKey,
    BadMessageFormat,
    BadMessageMac,
    BadMessageVersion,
    BadSessionKey,
    InvalidBase64,
    NotEnoughRandom,
    OutputBufferTooSmall,
    UnknownMessageIndex,
    Unknown,
}
impl fmt::Display for OlmGroupSessionError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let message = match self {
            OlmGroupSessionError::BadAccountKey => BAD_ACCOUNT_KEY,
            OlmGroupSessionError::BadSessionKey => BAD_SESSION_KEY,
            OlmGroupSessionError::UnknownMessageIndex => BAD_MSG_INDEX,
            OlmGroupSessionError::BadMessageFormat => BAD_MSG_FMT,
            OlmGroupSessionError::BadMessageMac => BAD_MSG_MAC,
            OlmGroupSessionError::BadMessageVersion => BAD_MSG_VERSION,
            OlmGroupSessionError::InvalidBase64 => INVALID_BASE64,
            OlmGroupSessionError::NotEnoughRandom => NOT_ENOUGH_RAND,
            OlmGroupSessionError::OutputBufferTooSmall => BUFFER_SMALL,
            OlmGroupSessionError::Unknown => UNKNOWN,
        };
        write!(f, "{}", message)
    }
}
#[derive(Debug, PartialEq)]
pub enum OlmSasError {
    NotEnoughRandom,
    OutputBufferTooSmall,
    InputBufferTooSmall,
    OtherPublicKeyUnset,
    InvalidLength,
    Unknown,
}
impl fmt::Display for OlmSasError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let message = match self {
            OlmSasError::NotEnoughRandom => NOT_ENOUGH_RAND,
            OlmSasError::OutputBufferTooSmall => BUFFER_SMALL,
            OlmSasError::InputBufferTooSmall => INPUT_BUFFER_SMALL,
            OlmSasError::OtherPublicKeyUnset => "The other public key isn't set",
            OlmSasError::InvalidLength => "The length can't be zero",
            OlmSasError::Unknown => UNKNOWN,
        };
        write!(f, "{}", message)
    }
}
#[derive(Debug, PartialEq)]
pub enum OlmPkSigningError {
    InvalidSeed,
    OutputBufferTooSmall,
    InputBufferTooSmall,
    Unknown,
}
impl fmt::Display for OlmPkSigningError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let message = match self {
            OlmPkSigningError::InvalidSeed => "The given seed is too short",
            OlmPkSigningError::OutputBufferTooSmall => BUFFER_SMALL,
            OlmPkSigningError::InputBufferTooSmall => INPUT_BUFFER_SMALL,
            OlmPkSigningError::Unknown => UNKNOWN,
        };
        write!(f, "{}", message)
    }
}
impl From<&str> for OlmPkSigningError {
    fn from(value: &str) -> Self {
        match value {
            "OUTPUT_BUFFER_TOO_SMALL" => OlmPkSigningError::OutputBufferTooSmall,
            "INPUT_BUFFER_TOO_SMALL" => OlmPkSigningError::OutputBufferTooSmall,
            _ => OlmPkSigningError::Unknown,
        }
    }
}
#[derive(Debug, PartialEq)]
pub enum OlmPkEncryptionError {
    OutputBufferTooSmall,
    InputBufferTooSmall,
    Unknown,
}
impl fmt::Display for OlmPkEncryptionError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let message = match self {
            OlmPkEncryptionError::OutputBufferTooSmall => BUFFER_SMALL,
            OlmPkEncryptionError::InputBufferTooSmall => INPUT_BUFFER_SMALL,
            OlmPkEncryptionError::Unknown => UNKNOWN,
        };
        write!(f, "{}", message)
    }
}
impl From<&str> for OlmPkEncryptionError {
    fn from(value: &str) -> Self {
        match value {
            "OUTPUT_BUFFER_TOO_SMALL" => OlmPkEncryptionError::OutputBufferTooSmall,
            "INPUT_BUFFER_TOO_SMALL" => OlmPkEncryptionError::OutputBufferTooSmall,
            _ => OlmPkEncryptionError::Unknown,
        }
    }
}
#[derive(Debug, PartialEq)]
pub enum OlmPkDecryptionError {
    BadAccountKey,
    BadMessageMac,
    InvalidBase64,
    OutputBufferTooSmall,
    InputBufferTooSmall,
    Unknown(String),
}
impl fmt::Display for OlmPkDecryptionError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let message = match self {
            OlmPkDecryptionError::InvalidBase64 => INVALID_BASE64,
            OlmPkDecryptionError::BadAccountKey => BAD_ACCOUNT_KEY,
            OlmPkDecryptionError::BadMessageMac => BAD_MSG_MAC,
            OlmPkDecryptionError::OutputBufferTooSmall => BUFFER_SMALL,
            OlmPkDecryptionError::InputBufferTooSmall => INPUT_BUFFER_SMALL,
            OlmPkDecryptionError::Unknown(e) => e,
        };
        write!(f, "{}", message)
    }
}
impl From<&str> for OlmPkDecryptionError {
    fn from(value: &str) -> Self {
        match value {
            "INVALID_BASE64" => OlmPkDecryptionError::InvalidBase64,
            "BAD_MESSAGE_MAC" => OlmPkDecryptionError::BadMessageMac,
            "BAD_ACCOUNT_KEY" => OlmPkDecryptionError::BadAccountKey,
            "OUTPUT_BUFFER_TOO_SMALL" => OlmPkDecryptionError::OutputBufferTooSmall,
            "INPUT_BUFFER_TOO_SMALL" => OlmPkDecryptionError::OutputBufferTooSmall,
            m => OlmPkDecryptionError::Unknown(m.to_owned()),
        }
    }
}