module Tendermint.SDK.BaseApp.Query
  ( serveQueryApplication
  -- * Re-Exports
  , HasQueryRouter(..)
  , StoreLeaf
  , storeQueryHandler
  , QueryEffs
  , module Tendermint.SDK.BaseApp.Query.Types
  ) where

import           Control.Lens                          ((&), (.~))
import           Data.Default.Class                    (def)
import           Data.Proxy
import qualified Network.ABCI.Types.Messages.Response  as Response
import           Polysemy                              (Sem)
import           Tendermint.SDK.BaseApp.Errors         (makeAppError,
                                                        queryAppError)
import           Tendermint.SDK.BaseApp.Query.Effect   (QueryEffs)
import           Tendermint.SDK.BaseApp.Query.Router   (HasQueryRouter (..))
import           Tendermint.SDK.BaseApp.Query.Store
import           Tendermint.SDK.BaseApp.Query.Types
import           Tendermint.SDK.BaseApp.Router.Delayed (emptyDelayed)
import           Tendermint.SDK.BaseApp.Router.Router  (runRouter)
import           Tendermint.SDK.BaseApp.Router.Types   (Application,
                                                        RouteResult (..))
import           Tendermint.SDK.Types.Effects          ((:&))

serveQueryApplication
  :: HasQueryRouter layout r
  => Proxy layout
  -> Proxy r
  -> RouteQ layout (QueryEffs :& r)
  -> QueryApplication (Sem r)
serveQueryApplication :: Proxy layout
-> Proxy r
-> RouteQ layout (QueryEffs :& r)
-> QueryApplication (Sem r)
serveQueryApplication pl :: Proxy layout
pl pr :: Proxy r
pr server :: RouteQ layout (QueryEffs :& r)
server =
  Application (Sem r) QueryRequest Query -> QueryApplication (Sem r)
forall (r :: EffectRow).
Application (Sem r) QueryRequest Query -> QueryApplication (Sem r)
toQueryApplication (Router () r QueryRequest Query
-> () -> Application (Sem r) QueryRequest Query
forall req env (r :: EffectRow) res.
HasPath req =>
Router env r req res -> env -> Application (Sem r) req res
runRouter (Proxy layout
-> Proxy r
-> Delayed (Sem r) () QueryRequest (RouteQ layout (QueryEffs :& r))
-> Router () r QueryRequest Query
forall k (layout :: k) (r :: EffectRow) env.
HasQueryRouter layout r =>
Proxy layout
-> Proxy r
-> Delayed
     (Sem r) env QueryRequest (RouteQ layout (QueryEffs :& r))
-> Router env r QueryRequest Query
routeQ Proxy layout
pl Proxy r
pr (RouteResult (RouteQ layout (ReadStore : Error AppError : r))
-> Delayed
     (Sem r)
     ()
     QueryRequest
     (RouteQ layout (ReadStore : Error AppError : r))
forall (m :: * -> *) a b req.
Monad m =>
RouteResult a -> Delayed m b req a
emptyDelayed (RouteQ layout (ReadStore : Error AppError : r)
-> RouteResult (RouteQ layout (ReadStore : Error AppError : r))
forall a. a -> RouteResult a
Route RouteQ layout (ReadStore : Error AppError : r)
RouteQ layout (QueryEffs :& r)
server))) ())

toQueryApplication
  :: Application (Sem r) QueryRequest Response.Query
  -> QueryApplication (Sem r)
toQueryApplication :: Application (Sem r) QueryRequest Query -> QueryApplication (Sem r)
toQueryApplication ra :: Application (Sem r) QueryRequest Query
ra query :: Query
query = do
  RouteResult Query
res <- Application (Sem r) QueryRequest Query
ra Application (Sem r) QueryRequest Query
-> Application (Sem r) QueryRequest Query
forall a b. (a -> b) -> a -> b
$ Query -> QueryRequest
parseQueryRequest Query
query
  case RouteResult Query
res of
    Fail e :: RouterError
e      -> Query -> Sem r Query
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Query -> Sem r Query) -> Query -> Sem r Query
forall a b. (a -> b) -> a -> b
$ Query
forall a. Default a => a
def Query -> (Query -> Query) -> Query
forall a b. a -> (a -> b) -> b
& (AppError -> Identity AppError) -> Query -> Identity Query
Lens' Query AppError
queryAppError ((AppError -> Identity AppError) -> Query -> Identity Query)
-> AppError -> Query -> Query
forall s t a b. ASetter s t a b -> b -> s -> t
.~ RouterError -> AppError
forall e. IsAppError e => e -> AppError
makeAppError RouterError
e
    FailFatal e :: RouterError
e -> Query -> Sem r Query
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Query -> Sem r Query) -> Query -> Sem r Query
forall a b. (a -> b) -> a -> b
$ Query
forall a. Default a => a
def Query -> (Query -> Query) -> Query
forall a b. a -> (a -> b) -> b
& (AppError -> Identity AppError) -> Query -> Identity Query
Lens' Query AppError
queryAppError ((AppError -> Identity AppError) -> Query -> Identity Query)
-> AppError -> Query -> Query
forall s t a b. ASetter s t a b -> b -> s -> t
.~ RouterError -> AppError
forall e. IsAppError e => e -> AppError
makeAppError RouterError
e
    Route a :: Query
a     -> Query -> Sem r Query
forall (f :: * -> *) a. Applicative f => a -> f a
pure Query
a