module Network.Wai.Predicate.Error
    ( Error
    , Reason (..)
    , err
    , e400
    , e405
    , e406
    , e415
    , e500
    , status
    , message
    , reason
    , source
    , labels
    , setStatus
    , setMessage
    , setReason
    , setSource
    , addLabel
    , isReasonOf
    ) where

import Data.ByteString (ByteString)
import Network.HTTP.Types.Status

data Reason
    = NotAvailable
    | TypeError
    deriving (Reason -> Reason -> Bool
(Reason -> Reason -> Bool)
-> (Reason -> Reason -> Bool) -> Eq Reason
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Reason -> Reason -> Bool
$c/= :: Reason -> Reason -> Bool
== :: Reason -> Reason -> Bool
$c== :: Reason -> Reason -> Bool
Eq, Int -> Reason -> ShowS
[Reason] -> ShowS
Reason -> String
(Int -> Reason -> ShowS)
-> (Reason -> String) -> ([Reason] -> ShowS) -> Show Reason
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Reason] -> ShowS
$cshowList :: [Reason] -> ShowS
show :: Reason -> String
$cshow :: Reason -> String
showsPrec :: Int -> Reason -> ShowS
$cshowsPrec :: Int -> Reason -> ShowS
Show)

-- | The error type used as meta-data for @Fail@ in all WAI predicates.
data Error = Error
    { Error -> Status
status  :: !Status          -- ^ HTTP status code
    , Error -> Maybe ByteString
message :: Maybe ByteString -- ^ optional status message
    , Error -> Maybe Reason
reason  :: Maybe Reason     -- ^ optional reason for this error
    , Error -> Maybe ByteString
source  :: Maybe ByteString -- ^ optional source of this erro
    , Error -> [ByteString]
labels  :: [ByteString]     -- ^ optional free-text labels
    } deriving (Error -> Error -> Bool
(Error -> Error -> Bool) -> (Error -> Error -> Bool) -> Eq Error
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Error -> Error -> Bool
$c/= :: Error -> Error -> Bool
== :: Error -> Error -> Bool
$c== :: Error -> Error -> Bool
Eq, Int -> Error -> ShowS
[Error] -> ShowS
Error -> String
(Int -> Error -> ShowS)
-> (Error -> String) -> ([Error] -> ShowS) -> Show Error
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Error] -> ShowS
$cshowList :: [Error] -> ShowS
show :: Error -> String
$cshow :: Error -> String
showsPrec :: Int -> Error -> ShowS
$cshowsPrec :: Int -> Error -> ShowS
Show)

err :: Status -> Error
err :: Status -> Error
err Status
s = Status
-> Maybe ByteString
-> Maybe Reason
-> Maybe ByteString
-> [ByteString]
-> Error
Error Status
s Maybe ByteString
forall a. Maybe a
Nothing Maybe Reason
forall a. Maybe a
Nothing Maybe ByteString
forall a. Maybe a
Nothing []

setStatus :: Status -> Error -> Error
setStatus :: Status -> Error -> Error
setStatus Status
s Error
e = Error
e { status :: Status
status = Status
s }

setMessage :: ByteString -> Error -> Error
setMessage :: ByteString -> Error -> Error
setMessage ByteString
m Error
e = Error
e { message :: Maybe ByteString
message = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
m }

setReason :: Reason -> Error -> Error
setReason :: Reason -> Error -> Error
setReason Reason
r Error
e = Error
e { reason :: Maybe Reason
reason = Reason -> Maybe Reason
forall a. a -> Maybe a
Just Reason
r }

setSource :: ByteString -> Error -> Error
setSource :: ByteString -> Error -> Error
setSource ByteString
s Error
e = Error
e { source :: Maybe ByteString
source = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
s }

addLabel :: ByteString -> Error -> Error
addLabel :: ByteString -> Error -> Error
addLabel ByteString
l Error
e = Error
e { labels :: [ByteString]
labels = ByteString
l ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: Error -> [ByteString]
labels Error
e }

isReasonOf :: Reason -> Error -> Bool
isReasonOf :: Reason -> Error -> Bool
isReasonOf Reason
r Error
e = Bool -> (Reason -> Bool) -> Maybe Reason -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Reason
r Reason -> Reason -> Bool
forall a. Eq a => a -> a -> Bool
==) (Error -> Maybe Reason
reason Error
e)

e400, e405, e406, e415, e500 :: Error
e400 :: Error
e400 = Status -> Error
err Status
status400
e405 :: Error
e405 = Status -> Error
err Status
status405
e406 :: Error
e406 = Status -> Error
err Status
status406
e415 :: Error
e415 = Status -> Error
err Status
status415
e500 :: Error
e500 = Status -> Error
err Status
status500