{-# LANGUAGE PatternSynonyms #-}

module Network.QUIC.Types.Error where

import qualified Network.TLS as TLS
import Network.TLS.QUIC
import Text.Printf

-- | Transport errors of QUIC.
newtype TransportError = TransportError Int deriving (Eq)

{- FOURMOLU_DISABLE -}
pattern NoError                 :: TransportError
pattern NoError                  = TransportError  0x0

pattern InternalError           :: TransportError
pattern InternalError            = TransportError  0x1

pattern ConnectionRefused       :: TransportError
pattern ConnectionRefused        = TransportError  0x2

pattern FlowControlError        :: TransportError
pattern FlowControlError         = TransportError  0x3

pattern StreamLimitError        :: TransportError
pattern StreamLimitError         = TransportError  0x4

pattern StreamStateError        :: TransportError
pattern StreamStateError         = TransportError  0x5

pattern FinalSizeError          :: TransportError
pattern FinalSizeError           = TransportError  0x6

pattern FrameEncodingError      :: TransportError
pattern FrameEncodingError       = TransportError  0x7

pattern TransportParameterError :: TransportError
pattern TransportParameterError  = TransportError  0x8

pattern ConnectionIdLimitError  :: TransportError
pattern ConnectionIdLimitError   = TransportError  0x9

pattern ProtocolViolation       :: TransportError
pattern ProtocolViolation        = TransportError  0xa

pattern InvalidToken            :: TransportError
pattern InvalidToken             = TransportError  0xb

pattern ApplicationError        :: TransportError
pattern ApplicationError         = TransportError  0xc

pattern CryptoBufferExceeded    :: TransportError
pattern CryptoBufferExceeded     = TransportError  0xd

pattern KeyUpdateError          :: TransportError
pattern KeyUpdateError           = TransportError  0xe

pattern AeadLimitReached        :: TransportError
pattern AeadLimitReached         = TransportError  0xf

pattern NoViablePath            :: TransportError
pattern NoViablePath             = TransportError 0x10

pattern VersionNegotiationError :: TransportError
pattern VersionNegotiationError  = TransportError 0x11

instance Show TransportError where
    show (TransportError    0x0) = "NoError"
    show (TransportError    0x1) = "InternalError"
    show (TransportError    0x2) = "ConnectionRefused"
    show (TransportError    0x3) = "FlowControlError"
    show (TransportError    0x4) = "StreamLimitError"
    show (TransportError    0x5) = "StreamStateError"
    show (TransportError    0x6) = "FinalSizeError"
    show (TransportError    0x7) = "FrameEncodingError"
    show (TransportError    0x8) = "TransportParameterError"
    show (TransportError    0x9) = "ConnectionIdLimitError"
    show (TransportError    0xa) = "ProtocolViolation"
    show (TransportError    0xb) = "InvalidToken"
    show (TransportError    0xc) = "ApplicationError"
    show (TransportError    0xd) = "CryptoBufferExceeded"
    show (TransportError    0xe) = "KeyUpdateError"
    show (TransportError    0xf) = "AeadLimitReached"
    show (TransportError   0x10) = "NoViablePath"
    show (TransportError   0x11) = "VersionNegotiationError"
    show (TransportError      x)
      | 0x100 <= x && x <= 0x01ff = "TLS" ++ show (toAlertDescription $ fromIntegral (x - 0x100))
      | otherwise = "TransportError " ++ printf "%x" x
{- FOURMOLU_ENABLE -}

-- | Converting a TLS alert to a corresponding transport error.
cryptoError :: TLS.AlertDescription -> TransportError
cryptoError ad = TransportError ec
  where
    ec = 0x100 + fromIntegral (fromAlertDescription ad)

-- | Application protocol errors of QUIC.
newtype ApplicationProtocolError = ApplicationProtocolError Int
    deriving (Eq, Show)
