-- | Contains DNS types which users of the DNS library may need to use. Private
--   types are mostly kept in Network.DNS.Common

module Network.DNS.Types
  ( DNSType(..)
  , ResponseCode(..)
  , RR(..)
  , rrToType
  ) where

import qualified Data.ByteString as B
import Network.Socket (HostAddress, HostAddress6)
import Data.Word (Word32)

-- | Types of DNS resources. RFC 1035, 3.2.2.
data DNSType = A | NS | CNAME | SOA | PTR | MX | TXT | AAAA
             | UnknownDNSType  -- ^ This is for internal error handling
                               --   and should never be used or seen outside
                               --   Network.DNS
             deriving (Show, Eq, Ord)

instance Enum DNSType where
  fromEnum A = 1
  fromEnum NS = 2
  fromEnum CNAME = 5
  fromEnum SOA = 6
  fromEnum PTR = 12
  fromEnum MX = 15
  fromEnum TXT = 16
  fromEnum AAAA = 28
  fromEnum UnknownDNSType = error "fromEnum of UnknownDNSType"

  toEnum 1 = A
  toEnum 2 = NS
  toEnum 5 = CNAME
  toEnum 6 = SOA
  toEnum 12 = PTR
  toEnum 15 = MX
  toEnum 16 = TXT
  toEnum 28 = AAAA
  toEnum _ = UnknownDNSType

-- | Error codes. RFC 1035, 4.1.1.
data ResponseCode = NoError
                  -- | The name server was unable to interpret the query
                  | FormatError
                  -- | The name server was unable to process this query due to a problem with the name server
                  | ServerError
                  -- | Meaningful only for responses from an authoritative name server, this code signifies that the domain name referenced in the query does not exist
                  | NXDomain
                  -- | The name server does not support the requested kind of query.
                  | NotImplemented
                  -- | The name server refuses to perform the specified operation for policy reasons.  For example, a name server may not wish to provide the information to the particular requester, or a name server may not wish to perform a particular operation (e.g., zone transfer) for particular data.
                  | AccessDenied
                  deriving (Show, Eq, Enum, Bounded)

-- | Resource record types. There store the actual data in the DNS database.
--   There's one for each DNSType
data RR = RRCNAME [String]
        | RRMX [(Int, [String])]  -- ^ a list of preferences and hostnames
        | RRNS [String]
        | RRPTR [String]
        | RRSOA { soaName :: [String]
                , soaRname :: [String]
                , soaSerial :: Word32
                , soaRefresh :: Word32
                , soaRetry :: Word32
                , soaExpire :: Word32
                , soaMinTTL :: Word32 }
        | RRTXT B.ByteString
        | RRA [HostAddress]
        | RRAAAA [HostAddress6]
        deriving (Show)

-- | Given an RR, this tells you the resource type of it
rrToType :: RR -> DNSType
rrToType (RRCNAME _) = CNAME
rrToType (RRMX _) = MX
rrToType (RRNS _) = NS
rrToType (RRPTR _) = PTR
rrToType (RRSOA { }) = SOA
rrToType (RRTXT _) = TXT
rrToType (RRA _) = A
rrToType (RRAAAA _) = AAAA