{-# LANGUAGE DeriveGeneric #-}
module Snap.Helpers
    ( respondWith
    -- HTTP Codes
    , noContent
    , temporaryRedirect
    , badRequest
    , unauthorised
    , forbidden
    , notFound
    , internalServer
    , ok
    , serviceUnavaliable
    -- Responses with Http Codes
    , respondBadRequest
    , respondNotFound
    , respondInternalServer
    , respondNoContent
    -- Respond with an error
    , respondWithError
    , respondWithErrors
    -- Write Aeson into a response
    , writeJson
    ) where

import           Data.Aeson
import qualified Data.ByteString.Char8 as BSC
import           GHC.Generics
import qualified Snap.Core             as SC

respondWith :: SC.MonadSnap m => Int -> m ()
respondWith = SC.modifyResponse . SC.setResponseCode

noContent, temporaryRedirect, badRequest, unauthorised, forbidden, notFound, internalServer, ok, serviceUnavaliable :: Int
ok                 = 200
noContent          = 204
temporaryRedirect  = 302
badRequest         = 400
unauthorised       = 401
forbidden          = 403
notFound           = 404
internalServer     = 500
serviceUnavaliable = 503

respondBadRequest, respondNotFound, respondInternalServer, respondNoContent :: SC.MonadSnap m => m ()
respondBadRequest       = respondWith badRequest
respondNotFound         = respondWith notFound
respondInternalServer   = respondWith internalServer
respondNoContent        = respondWith noContent

respondWithError :: SC.MonadSnap m => Int -> String -> m ()
respondWithError errorCode response = respondWithErrors errorCode [response]

respondWithErrors :: SC.MonadSnap m => Int -> [String] -> m ()
respondWithErrors errorCode responses = do
  writeJson errorResponse
  respondWith errorCode
  where
    errorResponse = ErrorResponse responses

writeJson :: (SC.MonadSnap m, ToJSON a) => a -> m ()
writeJson a = do
  SC.modifyResponse . SC.setContentType . BSC.pack $ "application/json"
  SC.writeLBS $ encode a

data ErrorResponse = ErrorResponse
  { errorMessages :: [String]
  } deriving (Show, Generic)

instance ToJSON ErrorResponse