{-# LANGUAGE UndecidableInstances #-}

module Mensam.Client.Application.MensamClient where

import Mensam.Client.Application.HttpClient.Class
import Mensam.Client.Application.MensamClient.Class
import Mensam.Client.Application.Options.Class

import Control.Monad.Logger.CallStack
import Control.Monad.Trans
import Control.Monad.Trans.Compose
import Control.Monad.Trans.Control
import Control.Monad.Trans.Control.Identity
import Control.Monad.Trans.Reader
import Data.Kind
import Servant.Client

type MensamClientT :: (Type -> Type) -> Type -> Type
newtype MensamClientT m a = MkMensamClientT {forall (m :: * -> *) a. MensamClientT m a -> ReaderT ClientEnv m a
unMensamClientT :: ReaderT ClientEnv m a}
  deriving newtype (Functor (MensamClientT m)
Functor (MensamClientT m) =>
(forall a. a -> MensamClientT m a)
-> (forall a b.
    MensamClientT m (a -> b) -> MensamClientT m a -> MensamClientT m b)
-> (forall a b c.
    (a -> b -> c)
    -> MensamClientT m a -> MensamClientT m b -> MensamClientT m c)
-> (forall a b.
    MensamClientT m a -> MensamClientT m b -> MensamClientT m b)
-> (forall a b.
    MensamClientT m a -> MensamClientT m b -> MensamClientT m a)
-> Applicative (MensamClientT m)
forall a. a -> MensamClientT m a
forall a b.
MensamClientT m a -> MensamClientT m b -> MensamClientT m a
forall a b.
MensamClientT m a -> MensamClientT m b -> MensamClientT m b
forall a b.
MensamClientT m (a -> b) -> MensamClientT m a -> MensamClientT m b
forall a b c.
(a -> b -> c)
-> MensamClientT m a -> MensamClientT m b -> MensamClientT m c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
forall (m :: * -> *). Applicative m => Functor (MensamClientT m)
forall (m :: * -> *) a. Applicative m => a -> MensamClientT m a
forall (m :: * -> *) a b.
Applicative m =>
MensamClientT m a -> MensamClientT m b -> MensamClientT m a
forall (m :: * -> *) a b.
Applicative m =>
MensamClientT m a -> MensamClientT m b -> MensamClientT m b
forall (m :: * -> *) a b.
Applicative m =>
MensamClientT m (a -> b) -> MensamClientT m a -> MensamClientT m b
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> MensamClientT m a -> MensamClientT m b -> MensamClientT m c
$cpure :: forall (m :: * -> *) a. Applicative m => a -> MensamClientT m a
pure :: forall a. a -> MensamClientT m a
$c<*> :: forall (m :: * -> *) a b.
Applicative m =>
MensamClientT m (a -> b) -> MensamClientT m a -> MensamClientT m b
<*> :: forall a b.
MensamClientT m (a -> b) -> MensamClientT m a -> MensamClientT m b
$cliftA2 :: forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> MensamClientT m a -> MensamClientT m b -> MensamClientT m c
liftA2 :: forall a b c.
(a -> b -> c)
-> MensamClientT m a -> MensamClientT m b -> MensamClientT m c
$c*> :: forall (m :: * -> *) a b.
Applicative m =>
MensamClientT m a -> MensamClientT m b -> MensamClientT m b
*> :: forall a b.
MensamClientT m a -> MensamClientT m b -> MensamClientT m b
$c<* :: forall (m :: * -> *) a b.
Applicative m =>
MensamClientT m a -> MensamClientT m b -> MensamClientT m a
<* :: forall a b.
MensamClientT m a -> MensamClientT m b -> MensamClientT m a
Applicative, (forall a b. (a -> b) -> MensamClientT m a -> MensamClientT m b)
-> (forall a b. a -> MensamClientT m b -> MensamClientT m a)
-> Functor (MensamClientT m)
forall a b. a -> MensamClientT m b -> MensamClientT m a
forall a b. (a -> b) -> MensamClientT m a -> MensamClientT m b
forall (m :: * -> *) a b.
Functor m =>
a -> MensamClientT m b -> MensamClientT m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> MensamClientT m a -> MensamClientT m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> MensamClientT m a -> MensamClientT m b
fmap :: forall a b. (a -> b) -> MensamClientT m a -> MensamClientT m b
$c<$ :: forall (m :: * -> *) a b.
Functor m =>
a -> MensamClientT m b -> MensamClientT m a
<$ :: forall a b. a -> MensamClientT m b -> MensamClientT m a
Functor, Applicative (MensamClientT m)
Applicative (MensamClientT m) =>
(forall a b.
 MensamClientT m a -> (a -> MensamClientT m b) -> MensamClientT m b)
-> (forall a b.
    MensamClientT m a -> MensamClientT m b -> MensamClientT m b)
-> (forall a. a -> MensamClientT m a)
-> Monad (MensamClientT m)
forall a. a -> MensamClientT m a
forall a b.
MensamClientT m a -> MensamClientT m b -> MensamClientT m b
forall a b.
MensamClientT m a -> (a -> MensamClientT m b) -> MensamClientT m b
forall (m :: * -> *). Monad m => Applicative (MensamClientT m)
forall (m :: * -> *) a. Monad m => a -> MensamClientT m a
forall (m :: * -> *) a b.
Monad m =>
MensamClientT m a -> MensamClientT m b -> MensamClientT m b
forall (m :: * -> *) a b.
Monad m =>
MensamClientT m a -> (a -> MensamClientT m b) -> MensamClientT m b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
MensamClientT m a -> (a -> MensamClientT m b) -> MensamClientT m b
>>= :: forall a b.
MensamClientT m a -> (a -> MensamClientT m b) -> MensamClientT m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
MensamClientT m a -> MensamClientT m b -> MensamClientT m b
>> :: forall a b.
MensamClientT m a -> MensamClientT m b -> MensamClientT m b
$creturn :: forall (m :: * -> *) a. Monad m => a -> MensamClientT m a
return :: forall a. a -> MensamClientT m a
Monad)
  deriving newtype ((forall (m :: * -> *). Monad m => Monad (MensamClientT m)) =>
(forall (m :: * -> *) a. Monad m => m a -> MensamClientT m a)
-> MonadTrans MensamClientT
forall (m :: * -> *). Monad m => Monad (MensamClientT m)
forall (m :: * -> *) a. Monad m => m a -> MensamClientT m a
forall (t :: (* -> *) -> * -> *).
(forall (m :: * -> *). Monad m => Monad (t m)) =>
(forall (m :: * -> *) a. Monad m => m a -> t m a) -> MonadTrans t
$clift :: forall (m :: * -> *) a. Monad m => m a -> MensamClientT m a
lift :: forall (m :: * -> *) a. Monad m => m a -> MensamClientT m a
MonadTrans, MonadTrans MensamClientT
MonadTrans MensamClientT =>
(forall (m :: * -> *) a.
 Monad m =>
 (Run MensamClientT -> m a) -> MensamClientT m a)
-> (forall (m :: * -> *) a.
    Monad m =>
    m (StT MensamClientT a) -> MensamClientT m a)
-> MonadTransControl MensamClientT
forall (m :: * -> *) a.
Monad m =>
m (StT MensamClientT a) -> MensamClientT m a
forall (m :: * -> *) a.
Monad m =>
(Run MensamClientT -> m a) -> MensamClientT m a
forall (t :: (* -> *) -> * -> *).
MonadTrans t =>
(forall (m :: * -> *) a. Monad m => (Run t -> m a) -> t m a)
-> (forall (m :: * -> *) a. Monad m => m (StT t a) -> t m a)
-> MonadTransControl t
$cliftWith :: forall (m :: * -> *) a.
Monad m =>
(Run MensamClientT -> m a) -> MensamClientT m a
liftWith :: forall (m :: * -> *) a.
Monad m =>
(Run MensamClientT -> m a) -> MensamClientT m a
$crestoreT :: forall (m :: * -> *) a.
Monad m =>
m (StT MensamClientT a) -> MensamClientT m a
restoreT :: forall (m :: * -> *) a.
Monad m =>
m (StT MensamClientT a) -> MensamClientT m a
MonadTransControl, MonadTransControl MensamClientT
MonadTransControl MensamClientT =>
(forall (m :: * -> *) a.
 Monad m =>
 ((forall x. MensamClientT m x -> m x) -> m a) -> MensamClientT m a)
-> MonadTransControlIdentity MensamClientT
forall (m :: * -> *) a.
Monad m =>
((forall x. MensamClientT m x -> m x) -> m a) -> MensamClientT m a
forall (t :: (* -> *) -> * -> *).
MonadTransControl t =>
(forall (m :: * -> *) a.
 Monad m =>
 ((forall x. t m x -> m x) -> m a) -> t m a)
-> MonadTransControlIdentity t
$cliftWithIdentity :: forall (m :: * -> *) a.
Monad m =>
((forall x. MensamClientT m x -> m x) -> m a) -> MensamClientT m a
liftWithIdentity :: forall (m :: * -> *) a.
Monad m =>
((forall x. MensamClientT m x -> m x) -> m a) -> MensamClientT m a
MonadTransControlIdentity)

instance MonadIO m => MonadMensamClient (MensamClientT m) where
  mensamCall :: forall a. ClientM a -> MensamClientT m (Either ClientError a)
mensamCall ClientM a
call = ReaderT ClientEnv m (Either ClientError a)
-> MensamClientT m (Either ClientError a)
forall (m :: * -> *) a. ReaderT ClientEnv m a -> MensamClientT m a
MkMensamClientT (ReaderT ClientEnv m (Either ClientError a)
 -> MensamClientT m (Either ClientError a))
-> ReaderT ClientEnv m (Either ClientError a)
-> MensamClientT m (Either ClientError a)
forall a b. (a -> b) -> a -> b
$ do
    ClientEnv
clientEnv <- ReaderT ClientEnv m ClientEnv
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask
    IO (Either ClientError a)
-> ReaderT ClientEnv m (Either ClientError a)
forall a. IO a -> ReaderT ClientEnv m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either ClientError a)
 -> ReaderT ClientEnv m (Either ClientError a))
-> IO (Either ClientError a)
-> ReaderT ClientEnv m (Either ClientError a)
forall a b. (a -> b) -> a -> b
$ ClientM a -> ClientEnv -> IO (Either ClientError a)
forall a. ClientM a -> ClientEnv -> IO (Either ClientError a)
runClientM ClientM a
call ClientEnv
clientEnv

deriving via
  MensamClientT ((t2 :: (Type -> Type) -> Type -> Type) m)
  instance
    MonadIO (t2 m) => MonadMensamClient (ComposeT MensamClientT t2 m)

runMensamClientT :: MensamClientT m a -> ClientEnv -> m a
runMensamClientT :: forall (m :: * -> *) a. MensamClientT m a -> ClientEnv -> m a
runMensamClientT = ReaderT ClientEnv m a -> ClientEnv -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (ReaderT ClientEnv m a -> ClientEnv -> m a)
-> (MensamClientT m a -> ReaderT ClientEnv m a)
-> MensamClientT m a
-> ClientEnv
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MensamClientT m a -> ReaderT ClientEnv m a
forall (m :: * -> *) a. MensamClientT m a -> ReaderT ClientEnv m a
unMensamClientT

runAppMensamClientT ::
  (MonadIO m, MonadHttpClient m, MonadLogger m, MonadOptions m) =>
  MensamClientT m a ->
  m a
runAppMensamClientT :: forall (m :: * -> *) a.
(MonadIO m, MonadHttpClient m, MonadLogger m, MonadOptions m) =>
MensamClientT m a -> m a
runAppMensamClientT MensamClientT m a
tma = do
  Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
logInfo Text
"Creating HTTP client environment."
  Manager
manager <- m Manager
forall (m :: * -> *). MonadHttpClient m => m Manager
httpManager
  BaseUrl
baseUrl <- Options -> BaseUrl
optionBaseUrl (Options -> BaseUrl) -> m Options -> m BaseUrl
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Options
forall (m :: * -> *). MonadOptions m => m Options
options
  let clientEnv :: ClientEnv
clientEnv = Manager -> BaseUrl -> ClientEnv
mkClientEnv Manager
manager BaseUrl
baseUrl
  Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
logInfo Text
"Created HTTP client environment."
  MensamClientT m a -> ClientEnv -> m a
forall (m :: * -> *) a. MensamClientT m a -> ClientEnv -> m a
runMensamClientT MensamClientT m a
tma ClientEnv
clientEnv