use std::io;
use std::fmt;
use std::error::Error;

/// Result type for using with [`EmuleadError`].
pub type EmuleadResult<T> = Result<T, EmuleadError>;

/// Error type using for the project errors.
#[derive(Debug)]
pub enum EmuleadError {
    /// IO Error
    Io(io::Error),
    /// Rotate bytes error used in [`network::rotate_bytes_right`]
    RotateBytes(usize)
}

impl fmt::Display for EmuleadError {

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &EmuleadError::Io(ref err) => write!(f, "IO error: {}", err),
            err => write!(f, "Error: {}", err.description())
        }
    }
}

impl Error for EmuleadError {

    fn description(&self) -> &str
    {
        match *self {
            EmuleadError::Io(ref err) => err.description(),
            EmuleadError::RotateBytes(_) => "Rotate shift must be in 0-8 bits."
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            EmuleadError::Io(ref err) => Some(err),
            _ => None
        }
    }
}

impl From<io::Error> for EmuleadError {
    }
}

    fn from(err: io::Error) -> EmuleadError {
        EmuleadError::Io(err)