module Network.ABCI.Server where

import           Data.Conduit            (runConduit, (.|))
import qualified Data.Conduit.List       as CL
import           Data.Conduit.Network    (AppData, ServerSettings, appSink,
                                          appSource, runTCPServer,
                                          serverSettings)
import           Data.String             (fromString)
import           Network.ABCI.Server.App (App (..))
import qualified Network.ABCI.Server.App as App


-- | Default ABCI app network settings for serving on localhost at the
-- standard port.
defaultLocalSettings :: ServerSettings
defaultLocalSettings :: ServerSettings
defaultLocalSettings = Int -> HostPreference -> ServerSettings
serverSettings 26658 (HostPreference -> ServerSettings)
-> HostPreference -> ServerSettings
forall a b. (a -> b) -> a -> b
$ String -> HostPreference
forall a. IsString a => String -> a
fromString "0.0.0.0"

-- | Serve an ABCI application with custom 'ServerSettings' and a custom
-- action to perform on acquiring the socket resource.
serveAppWith
  :: ServerSettings
  -> (AppData -> IO ())
  -> App IO
  -> IO ()
serveAppWith :: ServerSettings -> (AppData -> IO ()) -> App IO -> IO ()
serveAppWith cfg :: ServerSettings
cfg onAquire :: AppData -> IO ()
onAquire app :: App IO
app = ServerSettings -> (AppData -> IO ()) -> IO ()
forall a. ServerSettings -> (AppData -> IO ()) -> IO a
runTCPServer ServerSettings
cfg ((AppData -> IO ()) -> IO ()) -> (AppData -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \appData :: AppData
appData -> do
  AppData -> IO ()
onAquire AppData
appData
  ConduitT () Void IO () -> IO ()
forall (m :: * -> *) r. Monad m => ConduitT () Void m r -> m r
runConduit (ConduitT () Void IO () -> IO ())
-> ConduitT () Void IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ AppData -> ConduitT () ByteString IO ()
forall ad (m :: * -> *) i.
(HasReadWrite ad, MonadIO m) =>
ad -> ConduitT i ByteString m ()
appSource AppData
appData
    ConduitT () ByteString IO ()
-> ConduitM ByteString Void IO () -> ConduitT () Void IO ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| (ByteString -> IO ByteString)
-> ConduitT ByteString ByteString IO ()
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> ConduitT a b m ()
CL.mapM ((LPByteStrings -> ByteString) -> IO LPByteStrings -> IO ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap LPByteStrings -> ByteString
App.unLPByteStrings (IO LPByteStrings -> IO ByteString)
-> (ByteString -> IO LPByteStrings) -> ByteString -> IO ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. App IO -> LPByteStrings -> IO LPByteStrings
forall (m :: * -> *).
Applicative m =>
App m -> LPByteStrings -> m LPByteStrings
App.runApp App IO
app (LPByteStrings -> IO LPByteStrings)
-> (ByteString -> LPByteStrings) -> ByteString -> IO LPByteStrings
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> LPByteStrings
App.LPByteStrings)
    ConduitT ByteString ByteString IO ()
-> ConduitM ByteString Void IO () -> ConduitM ByteString Void IO ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| AppData -> ConduitM ByteString Void IO ()
forall ad (m :: * -> *) o.
(HasReadWrite ad, MonadIO m) =>
ad -> ConduitT ByteString o m ()
appSink AppData
appData


-- | Serve an ABCI application with default local 'ServerSettings'
-- and a no-op on acquiring the socket resource.
serveApp :: App IO -> IO ()
serveApp :: App IO -> IO ()
serveApp = ServerSettings -> (AppData -> IO ()) -> App IO -> IO ()
serveAppWith ServerSettings
defaultLocalSettings AppData -> IO ()
forall a. Monoid a => a
mempty