content: -- | This module provides a 'Request' data type which contains components required for
  -- creation of an HTTP Request.
  --
  -- 'Request' data is built from type level API endpoints and the 'Hreq.Core.Client.BaseUrl.BaseUrl'
  -- with in the 'Hreq.Core.API.HasRequest.HasRequest' class instance.
  --
  {-# LANGUAGE DeriveFunctor #-}
  module Hreq.Core.Client.Request where
  
  import Prelude ()
  import Prelude.Compat
  
  import Data.ByteString (ByteString)
  import qualified Data.ByteString.Lazy as LBS
  import qualified Data.Sequence as Seq
  import Data.Text
  import Network.HTTP.Media (MediaType)
  import Network.HTTP.Types (Header, HeaderName, HttpVersion (..), Method, QueryItem, http11,
                             methodGet)
  import Web.HttpApiData (ToHttpApiData (..))
  
  import Hreq.Core.API.Streaming (GivesPooper)
  
  -- * Request
  data RequestF body = Request
    { reqPath        :: Text
    , reqMethod      :: Method
    , reqBody        :: Maybe (body, MediaType)
    , reqQueryString :: Seq.Seq QueryItem
    , reqHttpVersion :: HttpVersion
    , reqAccept      :: Maybe MediaType
    , reqHeaders     :: Seq.Seq Header
    } deriving (Show, Eq, Functor)
  
  
  -- | The Request body replica of the @http-client@ @RequestBody@.
  data RequestBody =
      RequestBodyLBS LBS.ByteString
    | RequestBodyBS ByteString
    | RequestBodyStream (GivesPooper ())
    deriving (Show, Eq)
  
  
  type Request = RequestF RequestBody
  
  -- * Default Request
  defaultRequest :: Request
  defaultRequest = Request
    { reqPath = ""
    , reqMethod = methodGet
    , reqBody = Nothing
    , reqQueryString = Seq.empty
    , reqHttpVersion = http11
    , reqAccept = Nothing
    , reqHeaders = Seq.empty
    }
  
  -- * Request helper functions
  appendMethod :: Method -> Request -> Request
  appendMethod method req = req { reqMethod = method }
  
  appendToPath :: Text -> Request -> Request
  appendToPath p req = req { reqPath = reqPath req <> "/" <> p }
  
  appendToQueryString
    :: QueryItem
    -> Request
    -> Request
  appendToQueryString queryItem req =
    req { reqQueryString =  reqQueryString req Seq.|> queryItem }
  
  addHeader :: ToHttpApiData a => HeaderName -> a -> Request -> Request
  addHeader name val req =
    req {reqHeaders = reqHeaders req Seq.|> (name, toHeader val) }
  
  setReqBody :: RequestBody -> MediaType -> Request -> Request
  setReqBody body mediaType req =
    req { reqBody = Just (body, mediaType) }
  