{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Trustworthy         #-}
module Network.MessagePack.Client (
  -- * MessagePack Client type
    Basic.Client
  , Basic.ClientT
  , Basic.execClient
  , runClient

  -- * Call RPC method
  , Basic.call

  -- * RPC error
  , Basic.RpcError (..)
  , Basic.RpcType
  ) where

import           Control.Applicative                 (Applicative, pure)
import           Control.Monad                       (when)
import           Control.Monad.Catch                 (catch)
import qualified Data.ByteString                     as S
import           Data.Default.Class                  (Default (..))

import           Network.MessagePack.Capabilities    (ClientCapability (..),
                                                      ServerCapability (..))
import qualified Network.MessagePack.Client.Basic    as Basic
import qualified Network.MessagePack.Client.Internal as Internal
import qualified Network.MessagePack.Protocol        as Protocol


useDefault :: (Applicative m, Default a) => Basic.RpcError -> m a
useDefault :: RpcError -> m a
useDefault RpcError
_ = a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
forall a. Default a => a
def


initClient :: Basic.Client ()
initClient :: Client ()
initClient = do
  [ServerCapability]
caps <- [ClientCapability] -> Client [ServerCapability]
Protocol.capabilitiesC [ClientCapability
CCapMethodList] Client [ServerCapability]
-> (RpcError -> Client [ServerCapability])
-> Client [ServerCapability]
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`catch` RpcError -> Client [ServerCapability]
forall (m :: * -> *) a.
(Applicative m, Default a) =>
RpcError -> m a
useDefault
  Bool -> Client () -> Client ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ServerCapability
SCapMethodList ServerCapability -> [ServerCapability] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ServerCapability]
caps) (Client () -> Client ()) -> Client () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
    [Text]
mths <- Client [Text]
Protocol.methodListC
    [Text] -> Client ()
forall (m :: * -> *). Monad m => [Text] -> ClientT m ()
Internal.setMethodList [Text]
mths


runClient :: S.ByteString -> Int -> Basic.Client a -> IO a
runClient :: ByteString -> Int -> Client a -> IO a
runClient ByteString
host Int
port Client a
client =
  ByteString -> Int -> Client a -> IO a
forall a. ByteString -> Int -> Client a -> IO a
Basic.execClient ByteString
host Int
port (Client ()
initClient Client () -> Client a -> Client a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Client a
client)