{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}

module Tesla.Internal.HTTP where

import           Control.Lens
import           Control.Monad.IO.Class (MonadIO (..))
import           Data.Aeson             (FromJSON (..))
import qualified Data.ByteString.Char8  as BC
import           Network.Wreq           (Options, asJSON, defaults, get, getWith, header, postWith, responseBody)
import           Network.Wreq.Types     (Postable)

import           Tesla.Auth

userAgent :: BC.ByteString
userAgent :: ByteString
userAgent = ByteString
"github.com/dustin/tesla 0.1"

defOpts :: Options
defOpts :: Options
defOpts = Options
defaults Options -> (Options -> Options) -> Options
forall a b. a -> (a -> b) -> b
& HeaderName -> Lens' Options [ByteString]
header HeaderName
"User-Agent" (([ByteString] -> Identity [ByteString])
 -> Options -> Identity Options)
-> [ByteString] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [ByteString
userAgent]

-- | Get a set of wreq options from an 'AuthInfo'.
authOpts :: AuthInfo -> Options
authOpts :: AuthInfo -> Options
authOpts AuthInfo{String
_bearerToken :: AuthInfo -> String
_password :: AuthInfo -> String
_email :: AuthInfo -> String
_clientSecret :: AuthInfo -> String
_clientID :: AuthInfo -> String
_bearerToken :: String
_password :: String
_email :: String
_clientSecret :: String
_clientID :: String
..} = Options
defOpts Options -> (Options -> Options) -> Options
forall a b. a -> (a -> b) -> b
& HeaderName -> Lens' Options [ByteString]
header HeaderName
"Authorization" (([ByteString] -> Identity [ByteString])
 -> Options -> Identity Options)
-> [ByteString] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [ByteString
"Bearer " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> String -> ByteString
BC.pack String
_bearerToken]

jget :: (FromJSON j, MonadIO m) => String -> m j
jget :: String -> m j
jget String
u = Getting j (Response j) j -> Response j -> j
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting j (Response j) j
forall body0 body1.
Lens (Response body0) (Response body1) body0 body1
responseBody (Response j -> j) -> m (Response j) -> m j
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Response j) -> m (Response j)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Response ByteString -> IO (Response j)
forall (m :: * -> *) a.
(MonadThrow m, FromJSON a) =>
Response ByteString -> m (Response a)
asJSON (Response ByteString -> IO (Response j))
-> IO (Response ByteString) -> IO (Response j)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> IO (Response ByteString)
get String
u)

jgetWith :: (FromJSON j, MonadIO m) => Options -> String -> m j
jgetWith :: Options -> String -> m j
jgetWith Options
opts String
u = Getting j (Response j) j -> Response j -> j
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting j (Response j) j
forall body0 body1.
Lens (Response body0) (Response body1) body0 body1
responseBody (Response j -> j) -> m (Response j) -> m j
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Response j) -> m (Response j)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Response ByteString -> IO (Response j)
forall (m :: * -> *) a.
(MonadThrow m, FromJSON a) =>
Response ByteString -> m (Response a)
asJSON (Response ByteString -> IO (Response j))
-> IO (Response ByteString) -> IO (Response j)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Options -> String -> IO (Response ByteString)
getWith Options
opts String
u)

jgetAuth :: (HasTeslaAuth m, FromJSON j, MonadIO m) => String -> m j
jgetAuth :: String -> m j
jgetAuth String
u = m AuthInfo
forall (m :: * -> *). HasTeslaAuth m => m AuthInfo
teslaAuth m AuthInfo -> (AuthInfo -> m j) -> m j
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \AuthInfo
a -> Getting j (Response j) j -> Response j -> j
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting j (Response j) j
forall body0 body1.
Lens (Response body0) (Response body1) body0 body1
responseBody (Response j -> j) -> m (Response j) -> m j
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Response j) -> m (Response j)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Response ByteString -> IO (Response j)
forall (m :: * -> *) a.
(MonadThrow m, FromJSON a) =>
Response ByteString -> m (Response a)
asJSON (Response ByteString -> IO (Response j))
-> IO (Response ByteString) -> IO (Response j)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Options -> String -> IO (Response ByteString)
getWith (AuthInfo -> Options
authOpts AuthInfo
a) String
u)

jpostWith :: (FromJSON j, Postable a, MonadIO m) => Options -> String -> a -> m j
jpostWith :: Options -> String -> a -> m j
jpostWith Options
opts String
u a
v = Getting j (Response j) j -> Response j -> j
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting j (Response j) j
forall body0 body1.
Lens (Response body0) (Response body1) body0 body1
responseBody (Response j -> j) -> m (Response j) -> m j
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Response j) -> m (Response j)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Options -> String -> a -> IO (Response ByteString)
forall a.
Postable a =>
Options -> String -> a -> IO (Response ByteString)
postWith Options
opts String
u a
v IO (Response ByteString)
-> (Response ByteString -> IO (Response j)) -> IO (Response j)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Response ByteString -> IO (Response j)
forall (m :: * -> *) a.
(MonadThrow m, FromJSON a) =>
Response ByteString -> m (Response a)
asJSON)

jpostAuth :: (HasTeslaAuth m, FromJSON j, Postable a, MonadIO m) => String -> a -> m j
jpostAuth :: String -> a -> m j
jpostAuth String
u a
v = m AuthInfo
forall (m :: * -> *). HasTeslaAuth m => m AuthInfo
teslaAuth m AuthInfo -> (AuthInfo -> m j) -> m j
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \AuthInfo
a -> Options -> String -> a -> m j
forall j a (m :: * -> *).
(FromJSON j, Postable a, MonadIO m) =>
Options -> String -> a -> m j
jpostWith (AuthInfo -> Options
authOpts AuthInfo
a) String
u a
v