use core::{
    array::TryFromSliceError,
    num::{ParseIntError, TryFromIntError},
    str::Utf8Error,
};
use std::string::FromUtf8Error;

use rapira::{EnumFromU8Error, RapiraError};
#[cfg(feature = "std")]
use thiserror::Error;
use zerocopy::{TryFromBytes, error::ValidityError};

#[cfg_attr(feature = "std", derive(Error, Debug))]
pub enum ArmourError {
    #[cfg_attr(feature = "std", error("from bytes error"))]
    FromBytesError,
    #[cfg_attr(feature = "std", error("bytes len error"))]
    BytesLenError,
    #[cfg_attr(feature = "std", error(transparent))]
    TryFromSliceError(#[from] TryFromSliceError),
    #[cfg_attr(feature = "std", error("NonZero is 0"))]
    NonZeroError,
    #[cfg_attr(feature = "std", error(transparent))]
    NonZero(#[from] TryFromIntError),
    #[cfg_attr(feature = "std", error(transparent))]
    ParseInt(#[from] ParseIntError),
    #[cfg_attr(feature = "std", error(transparent))]
    RapiraError(#[from] RapiraError),
    #[cfg_attr(feature = "std", error(transparent))]
    EnumFromU8(#[from] EnumFromU8Error),
    #[cfg_attr(feature = "std", error("zbase decode error"))]
    ZBaseDecodeError,
    #[cfg_attr(feature = "std", error("hex decode error"))]
    HexDecodeError,
    #[cfg_attr(feature = "std", error("unknown error"))]
    UnknownError,
    #[cfg_attr(feature = "std", error("hash index exist"))]
    HashIndexExist,
    #[cfg_attr(feature = "std", error("id decode error"))]
    IdDecodeError,
    #[cfg_attr(feature = "std", error("zerocopy validity error"))]
    ZerocopyValidityError,
    #[cfg_attr(feature = "std", error("utf8 decode error: {0}"))]
    FromUtf8Error(#[from] FromUtf8Error),
    #[cfg_attr(feature = "std", error("utf8 decode error: {0}"))]
    Utf8Error(#[from] Utf8Error),
}

impl<S, D: TryFromBytes> From<ValidityError<S, D>> for ArmourError {
    fn from(_: ValidityError<S, D>) -> Self {
        ArmourError::ZerocopyValidityError
    }
}
