use {Error};
use rdata::Record;
use rdata::*;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Type {
    
    A = a::Record::TYPE,
    
    NS = ns::Record::TYPE,
    
    MF = mf::Record::TYPE,
    
    CNAME = cname::Record::TYPE,
    
    SOA = soa::Record::TYPE,
    
    MB = mb::Record::TYPE,
    
    MG = mg::Record::TYPE,
    
    MR = mr::Record::TYPE,
    
    NULL = null::Record::TYPE,
    
    WKS = wks::Record::TYPE,
    
    PTR = ptr::Record::TYPE,
    
    HINFO = hinfo::Record::TYPE,
    
    MINFO = minfo::Record::TYPE,
    
    MX = mx::Record::TYPE,
    
    TXT = txt::Record::TYPE,
    
    AAAA = aaaa::Record::TYPE,
    
    SRV = srv::Record::TYPE,
    
    OPT = opt::Record::TYPE,
    
    NSEC = nsec::Record::TYPE,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
pub enum QueryType {
    
    A = a::Record::TYPE,
    
    NS = ns::Record::TYPE,
    
    MF = mf::Record::TYPE,
    
    CNAME = cname::Record::TYPE,
    
    SOA = soa::Record::TYPE,
    
    MB = mb::Record::TYPE,
    
    MG = mg::Record::TYPE,
    
    MR = mr::Record::TYPE,
    
    NULL = null::Record::TYPE,
    
    WKS = wks::Record::TYPE,
    
    PTR = ptr::Record::TYPE,
    
    HINFO = hinfo::Record::TYPE,
    
    MINFO = minfo::Record::TYPE,
    
    MX = mx::Record::TYPE,
    
    TXT = txt::Record::TYPE,
    
    AAAA = aaaa::Record::TYPE,
    
    SRV = srv::Record::TYPE,
    
    AXFR = axfr::Record::TYPE,
    
    MAILB = mailb::Record::TYPE,
    
    MAILA = maila::Record::TYPE,
    
    All = all::Record::TYPE,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Class {
    
    IN = 1,
    
    
    CS = 2,
    
    CH = 3,
    
    HS = 4,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum QueryClass {
    
    IN = 1,
    
    
    CS = 2,
    
    CH = 3,
    
    HS = 4,
    
    Any = 255,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Opcode {
    
    StandardQuery,
    
    InverseQuery,
    
    ServerStatusRequest,
    
    Reserved(u16),
}
quick_error! {
    
    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
    #[allow(missing_docs)] 
    pub enum ResponseCode {
        NoError
        FormatError
        ServerFailure
        NameError
        NotImplemented
        Refused
        Reserved(code: u8)
    }
}
impl From<u16> for Opcode {
    fn from(code: u16) -> Opcode {
        use self::Opcode::*;
        match code {
            0 => StandardQuery,
            1 => InverseQuery,
            2 => ServerStatusRequest,
            x => Reserved(x),
        }
    }
}
impl Into<u16> for Opcode {
    fn into(self) -> u16 {
        use self::Opcode::*;
        match self {
            StandardQuery => 0,
            InverseQuery => 1,
            ServerStatusRequest => 2,
            Reserved(x) => x,
        }
    }
}
impl From<u8> for ResponseCode {
    fn from(code: u8) -> ResponseCode {
        use self::ResponseCode::*;
        match code {
            0       => NoError,
            1       => FormatError,
            2       => ServerFailure,
            3       => NameError,
            4       => NotImplemented,
            5       => Refused,
            6...15  => Reserved(code),
            x       => panic!("Invalid response code {}", x),
        }
    }
}
impl Into<u8> for ResponseCode {
    fn into(self) -> u8 {
        use self::ResponseCode::*;
        match self {
            NoError         => 0,
            FormatError     => 1,
            ServerFailure   => 2,
            NameError       => 3,
            NotImplemented  => 4,
            Refused         => 5,
            Reserved(code)  => code,
        }
    }
}
impl QueryType {
    
    pub fn parse(code: u16) -> Result<QueryType, Error> {
        use self::QueryType::*;
        match code as isize {
            a::Record::TYPE         => Ok(A),
            ns::Record::TYPE        => Ok(NS),
            mf::Record::TYPE        => Ok(MF),
            cname::Record::TYPE     => Ok(CNAME),
            soa::Record::TYPE       => Ok(SOA),
            mb::Record::TYPE        => Ok(MB),
            mg::Record::TYPE        => Ok(MG),
            mr::Record::TYPE        => Ok(MR),
            null::Record::TYPE      => Ok(NULL),
            wks::Record::TYPE       => Ok(WKS),
            ptr::Record::TYPE       => Ok(PTR),
            hinfo::Record::TYPE     => Ok(HINFO),
            minfo::Record::TYPE     => Ok(MINFO),
            mx::Record::TYPE        => Ok(MX),
            txt::Record::TYPE       => Ok(TXT),
            aaaa::Record::TYPE      => Ok(AAAA),
            srv::Record::TYPE       => Ok(SRV),
            axfr::Record::TYPE      => Ok(AXFR),
            mailb::Record::TYPE     => Ok(MAILB),
            maila::Record::TYPE     => Ok(MAILA),
            all::Record::TYPE       => Ok(All),
            x               => Err(Error::InvalidQueryType(x as u16)),
        }
    }
}
impl QueryClass {
    
    pub fn parse(code: u16) -> Result<QueryClass, Error> {
        use self::QueryClass::*;
        match code {
            1   => Ok(IN),
            2   => Ok(CS),
            3   => Ok(CH),
            4   => Ok(HS),
            255 => Ok(Any),
            x   => Err(Error::InvalidQueryClass(x)),
        }
    }
}
impl Type {
    
    pub fn parse(code: u16) -> Result<Type, Error> {
        use self::Type::*;
        match code as isize {
            a::Record::TYPE         => Ok(A),
            ns::Record::TYPE        => Ok(NS),
            mf::Record::TYPE        => Ok(MF),
            cname::Record::TYPE     => Ok(CNAME),
            soa::Record::TYPE       => Ok(SOA),
            mb::Record::TYPE        => Ok(MB),
            mg::Record::TYPE        => Ok(MG),
            mr::Record::TYPE        => Ok(MR),
            null::Record::TYPE      => Ok(NULL),
            wks::Record::TYPE       => Ok(WKS),
            ptr::Record::TYPE       => Ok(PTR),
            hinfo::Record::TYPE     => Ok(HINFO),
            minfo::Record::TYPE     => Ok(MINFO),
            mx::Record::TYPE        => Ok(MX),
            txt::Record::TYPE       => Ok(TXT),
            aaaa::Record::TYPE      => Ok(AAAA),
            srv::Record::TYPE       => Ok(SRV),
            opt::Record::TYPE       => Ok(OPT),
            nsec::Record::TYPE      => Ok(NSEC),
            x               => Err(Error::InvalidType(x as u16)),
        }
    }
}
impl Class {
    
    pub fn parse(code: u16) -> Result<Class, Error> {
        use self::Class::*;
        match code {
            1   => Ok(IN),
            2   => Ok(CS),
            3   => Ok(CH),
            4   => Ok(HS),
            x   => Err(Error::InvalidClass(x)),
        }
    }
}