module Tendermint.SDK.BaseApp.Query.Effect
  ( QueryEffs
  , runQuery
  ) where

import           Control.Lens                           ((&), (.~))
import           Data.ByteArray.Base64String            (fromBytes)
import           Data.Default.Class                     (def)
import           Network.ABCI.Types.Messages.FieldTypes (WrappedVal (..))
import qualified Network.ABCI.Types.Messages.Response   as Response
import           Polysemy                               (Member, Sem)
import           Polysemy.Error                         (Error, runError)
import           Polysemy.Tagged                        (Tagged, tag)
import           Tendermint.SDK.BaseApp.Errors          (AppError,
                                                         queryAppError)
import           Tendermint.SDK.BaseApp.Query.Types
import           Tendermint.SDK.BaseApp.Store           (ReadStore, Scope (..))
import           Tendermint.SDK.Codec                   (HasCodec (..))
import           Tendermint.SDK.Types.Effects           ((:&))

type QueryEffs =
    '[ ReadStore
     , Error AppError
     ]

runQuery
  :: HasCodec a
  => Member (Tagged 'QueryAndMempool ReadStore) r
  => Sem (QueryEffs :& r) (QueryResult a)
  -> Sem r Response.Query
runQuery :: Sem (QueryEffs :& r) (QueryResult a) -> Sem r Query
runQuery query :: Sem (QueryEffs :& r) (QueryResult a)
query = do
  Either AppError (QueryResult a)
eRes <- Sem (QueryEffs :& r) (QueryResult a)
-> Sem r (Either AppError (QueryResult a))
forall (r :: [(* -> *) -> * -> *]) a.
Member (Tagged 'QueryAndMempool ReadStore) r =>
Sem (QueryEffs :& r) (QueryResult a)
-> Sem r (Either AppError (QueryResult a))
eval Sem (QueryEffs :& r) (QueryResult a)
query
  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
$ case Either AppError (QueryResult a)
eRes of
    Left e :: AppError
e -> 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
.~ AppError
e
    Right QueryResult{..}  ->
      Query
forall a. Default a => a
def
        Query -> (Query -> Query) -> Query
forall a b. a -> (a -> b) -> b
& (WrappedVal Int64 -> Identity (WrappedVal Int64))
-> Query -> Identity Query
Lens' Query (WrappedVal Int64)
Response._queryIndex ((WrappedVal Int64 -> Identity (WrappedVal Int64))
 -> Query -> Identity Query)
-> WrappedVal Int64 -> Query -> Query
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Int64 -> WrappedVal Int64
forall a. a -> WrappedVal a
WrappedVal Int64
queryResultIndex
        Query -> (Query -> Query) -> Query
forall a b. a -> (a -> b) -> b
& (Base64String -> Identity Base64String) -> Query -> Identity Query
Lens' Query Base64String
Response._queryKey ((Base64String -> Identity Base64String)
 -> Query -> Identity Query)
-> Base64String -> Query -> Query
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Base64String
queryResultKey
        Query -> (Query -> Query) -> Query
forall a b. a -> (a -> b) -> b
& (Base64String -> Identity Base64String) -> Query -> Identity Query
Lens' Query Base64String
Response._queryValue ((Base64String -> Identity Base64String)
 -> Query -> Identity Query)
-> Base64String -> Query -> Query
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ByteString -> Base64String
forall ba. ByteArrayAccess ba => ba -> Base64String
fromBytes (a -> ByteString
forall a. HasCodec a => a -> ByteString
encode a
queryResultData)
        Query -> (Query -> Query) -> Query
forall a b. a -> (a -> b) -> b
& (Maybe Proof -> Identity (Maybe Proof)) -> Query -> Identity Query
Lens' Query (Maybe Proof)
Response._queryProof ((Maybe Proof -> Identity (Maybe Proof))
 -> Query -> Identity Query)
-> Maybe Proof -> Query -> Query
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Maybe Proof
queryResultProof
        Query -> (Query -> Query) -> Query
forall a b. a -> (a -> b) -> b
& (WrappedVal Int64 -> Identity (WrappedVal Int64))
-> Query -> Identity Query
Lens' Query (WrappedVal Int64)
Response._queryHeight ((WrappedVal Int64 -> Identity (WrappedVal Int64))
 -> Query -> Identity Query)
-> WrappedVal Int64 -> Query -> Query
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Int64 -> WrappedVal Int64
forall a. a -> WrappedVal a
WrappedVal Int64
queryResultHeight

eval
  :: Member (Tagged 'QueryAndMempool ReadStore) r
  => Sem (QueryEffs :& r) (QueryResult a)
  -> Sem r (Either AppError (QueryResult a))
eval :: Sem (QueryEffs :& r) (QueryResult a)
-> Sem r (Either AppError (QueryResult a))
eval = Sem (Error AppError : r) (QueryResult a)
-> Sem r (Either AppError (QueryResult a))
forall e (r :: [(* -> *) -> * -> *]) a.
Sem (Error e : r) a -> Sem r (Either e a)
runError (Sem (Error AppError : r) (QueryResult a)
 -> Sem r (Either AppError (QueryResult a)))
-> (Sem (ReadStore : Error AppError : r) (QueryResult a)
    -> Sem (Error AppError : r) (QueryResult a))
-> Sem (ReadStore : Error AppError : r) (QueryResult a)
-> Sem r (Either AppError (QueryResult a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem (ReadStore : Error AppError : r) (QueryResult a)
-> Sem (Error AppError : r) (QueryResult a)
forall k1 (k2 :: k1) (e :: (* -> *) -> * -> *)
       (r :: [(* -> *) -> * -> *]) a.
Member (Tagged k2 e) r =>
Sem (e : r) a -> Sem r a
tag