{-# LANGUAGE OverloadedStrings #-}
module Network.API.Mandrill.HTTP where

import           Control.Applicative
import           Data.Aeson
import           Data.Monoid
import qualified Data.Text                     as T
import           Network.API.Mandrill.Settings
import           Network.API.Mandrill.Types
import           Network.HTTP.Client
import           Network.HTTP.Client.TLS
import           Network.HTTP.Types

toMandrillResponse :: (MandrillEndpoint ep, FromJSON a, ToJSON rq)
                   => ep
                   -> rq
                   -> Maybe Manager
                   -> IO (MandrillResponse a)
toMandrillResponse :: ep -> rq -> Maybe Manager -> IO (MandrillResponse a)
toMandrillResponse ep
ep rq
rq Maybe Manager
mbMgr = do
  let fullUrl :: Text
fullUrl = Text
mandrillUrl Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ep -> Text
forall ep. MandrillEndpoint ep => ep -> Text
toUrl ep
ep
  Request
rq' <- String -> IO Request
forall (m :: * -> *). MonadThrow m => String -> m Request
parseRequest (Text -> String
T.unpack Text
fullUrl)
  let headers :: [(HeaderName, ByteString)]
headers = [(HeaderName
hContentType, ByteString
"application/json")]
  let jsonBody :: ByteString
jsonBody = rq -> ByteString
forall a. ToJSON a => a -> ByteString
encode rq
rq
  let req :: Request
req = Request
rq' {
        method :: ByteString
method = ByteString
"POST"
      , requestHeaders :: [(HeaderName, ByteString)]
requestHeaders = [(HeaderName, ByteString)]
headers
      , requestBody :: RequestBody
requestBody = ByteString -> RequestBody
RequestBodyLBS ByteString
jsonBody
      }
  Manager
mgr <- IO Manager
-> (Manager -> IO Manager) -> Maybe Manager -> IO Manager
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (ManagerSettings -> IO Manager
newManager ManagerSettings
tlsManagerSettings) Manager -> IO Manager
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Manager
mbMgr
  ByteString
res <- Response ByteString -> ByteString
forall body. Response body -> body
responseBody (Response ByteString -> ByteString)
-> IO (Response ByteString) -> IO ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Request -> Manager -> IO (Response ByteString)
httpLbs Request
req Manager
mgr
  case ByteString -> Either String (MandrillResponse a)
forall a. FromJSON a => ByteString -> Either String a
eitherDecode ByteString
res of
    Left String
e ->  String -> IO (MandrillResponse a)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
e
    Right MandrillResponse a
v -> MandrillResponse a -> IO (MandrillResponse a)
forall (m :: * -> *) a. Monad m => a -> m a
return MandrillResponse a
v