{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE KindSignatures      #-}
{-# LANGUAGE NamedFieldPuns      #-}
{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Ouroboros.Network.Protocol.LocalStateQuery.Client
  ( -- * Protocol type for the client
    -- | The protocol states from the point of view of the client.
    LocalStateQueryClient (..)
  , ClientStIdle (..)
  , ClientStAcquiring (..)
  , ClientStAcquired (..)
  , ClientStQuerying (..)
    -- * Execution as a typed protocol
  , localStateQueryClientPeer
    -- * Null local state query client
  , localStateQueryClientNull
    -- * Utilities
  , mapLocalStateQueryClient
  , Some (..)
  ) where

import           Control.Monad (forever)
import           Control.Monad.Class.MonadTimer
import           Data.Kind (Type)

import           Network.TypedProtocol.Core

import           Ouroboros.Network.Protocol.LocalStateQuery.Codec (Some (..))
import           Ouroboros.Network.Protocol.LocalStateQuery.Type


newtype LocalStateQueryClient block point (query :: Type -> Type) m a =
    LocalStateQueryClient {
      LocalStateQueryClient block point query m a
-> m (ClientStIdle block point query m a)
runLocalStateQueryClient :: m (ClientStIdle block point query m a)
    }

localStateQueryClientNull :: MonadTimer m => LocalStateQueryClient block point query m a
localStateQueryClientNull :: LocalStateQueryClient block point query m a
localStateQueryClientNull =
    m (ClientStIdle block point query m a)
-> LocalStateQueryClient block point query m a
forall block point (query :: * -> *) (m :: * -> *) a.
m (ClientStIdle block point query m a)
-> LocalStateQueryClient block point query m a
LocalStateQueryClient (m (ClientStIdle block point query m a)
 -> LocalStateQueryClient block point query m a)
-> m (ClientStIdle block point query m a)
-> LocalStateQueryClient block point query m a
forall a b. (a -> b) -> a -> b
$ m () -> m (ClientStIdle block point query m a)
forall (f :: * -> *) a b. Applicative f => f a -> f b
forever (m () -> m (ClientStIdle block point query m a))
-> m () -> m (ClientStIdle block point query m a)
forall a b. (a -> b) -> a -> b
$ DiffTime -> m ()
forall (m :: * -> *). MonadDelay m => DiffTime -> m ()
threadDelay DiffTime
43200 {- day in seconds -}

{-# DEPRECATED localStateQueryClientNull "Use Ouroboros.Network.NodeToClient.localStateQueryPeerNull" #-}

-- | In the 'StIdle' protocol state, the client has agency and must send:
--
--  * a request to acquire a state
--  * a termination messge
--
data ClientStIdle block point query (m :: Type -> Type) a where
  SendMsgAcquire :: Maybe point
                 -> ClientStAcquiring block point query m a
                 -> ClientStIdle      block point query m a

  SendMsgDone    :: a
                 -> ClientStIdle      block point query m a

-- | In the 'StAcquiring' protocol state, the client does not have agency.
-- Instead it is waiting for:
--
--  * acquired
--  * failure to acquire
--
-- It must be prepared to handle either.
--
data ClientStAcquiring block point query m a = ClientStAcquiring {
      ClientStAcquiring block point query m a
-> m (ClientStAcquired block point query m a)
recvMsgAcquired :: m (ClientStAcquired block point query m a),

      ClientStAcquiring block point query m a
-> AcquireFailure -> m (ClientStIdle block point query m a)
recvMsgFailure  :: AcquireFailure
                      -> m (ClientStIdle  block point query m a)
    }

-- | In the 'StAcquired' protocol state, the client has agency and must send:
--
--  * a query
--  * a request to (re)acquire another state
--  * a release of the current state
--
data ClientStAcquired block point query m a where
  SendMsgQuery     :: query result
                   -> ClientStQuerying block point query m a result
                   -> ClientStAcquired block point query m a

  SendMsgReAcquire :: Maybe point
                   -> ClientStAcquiring block point query m a
                   -> ClientStAcquired  block point query m a

  SendMsgRelease   :: m (ClientStIdle   block point query m a)
                   -> ClientStAcquired  block point query m a

-- | In the 'StQuerying' protocol state, the client does not have agency.
-- Instead it is waiting for:
--
--  * a result
--
data ClientStQuerying block point query m a result = ClientStQuerying {
      ClientStQuerying block point query m a result
-> result -> m (ClientStAcquired block point query m a)
recvMsgResult :: result -> m (ClientStAcquired block point query m a)
    }

-- | Transform a 'LocalStateQueryClient' by mapping over the query and query
-- result values.
--
-- Note the direction of the individual mapping functions corresponds to
-- whether the types are used as protocol inputs or outputs.
--
mapLocalStateQueryClient :: forall block block' point point' query query' m a.
                            Functor m
                         => (point -> point')
                         -> (forall result. query result -> Some query')
                         -> (forall result result'.
                                    query result
                                 -> query' result'
                                 -> result' -> result)
                         -> LocalStateQueryClient block  point  query  m a
                         -> LocalStateQueryClient block' point' query' m a
mapLocalStateQueryClient :: (point -> point')
-> (forall result. query result -> Some query')
-> (forall result result'.
    query result -> query' result' -> result' -> result)
-> LocalStateQueryClient block point query m a
-> LocalStateQueryClient block' point' query' m a
mapLocalStateQueryClient point -> point'
fpoint forall result. query result -> Some query'
fquery forall result result'.
query result -> query' result' -> result' -> result
fresult =
    \(LocalStateQueryClient m (ClientStIdle block point query m a)
c) -> m (ClientStIdle block' point' query' m a)
-> LocalStateQueryClient block' point' query' m a
forall block point (query :: * -> *) (m :: * -> *) a.
m (ClientStIdle block point query m a)
-> LocalStateQueryClient block point query m a
LocalStateQueryClient ((ClientStIdle block point query m a
 -> ClientStIdle block' point' query' m a)
-> m (ClientStIdle block point query m a)
-> m (ClientStIdle block' point' query' m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ClientStIdle block point query m a
-> ClientStIdle block' point' query' m a
goIdle m (ClientStIdle block point query m a)
c)
  where
    goIdle :: ClientStIdle block  point  query  m a
           -> ClientStIdle block' point' query' m a
    goIdle :: ClientStIdle block point query m a
-> ClientStIdle block' point' query' m a
goIdle (SendMsgAcquire Maybe point
pt ClientStAcquiring block point query m a
k) =
      Maybe point'
-> ClientStAcquiring block' point' query' m a
-> ClientStIdle block' point' query' m a
forall point block (query :: * -> *) (m :: * -> *) a.
Maybe point
-> ClientStAcquiring block point query m a
-> ClientStIdle block point query m a
SendMsgAcquire (point -> point'
fpoint (point -> point') -> Maybe point -> Maybe point'
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe point
pt) (ClientStAcquiring block point query m a
-> ClientStAcquiring block' point' query' m a
goAcquiring ClientStAcquiring block point query m a
k)

    goIdle (SendMsgDone a
a) = a -> ClientStIdle block' point' query' m a
forall a block point (query :: * -> *) (m :: * -> *).
a -> ClientStIdle block point query m a
SendMsgDone a
a

    goAcquiring :: ClientStAcquiring block  point  query  m a
                -> ClientStAcquiring block' point' query' m a
    goAcquiring :: ClientStAcquiring block point query m a
-> ClientStAcquiring block' point' query' m a
goAcquiring ClientStAcquiring { m (ClientStAcquired block point query m a)
recvMsgAcquired :: m (ClientStAcquired block point query m a)
recvMsgAcquired :: forall block point (query :: * -> *) (m :: * -> *) a.
ClientStAcquiring block point query m a
-> m (ClientStAcquired block point query m a)
recvMsgAcquired, AcquireFailure -> m (ClientStIdle block point query m a)
recvMsgFailure :: AcquireFailure -> m (ClientStIdle block point query m a)
recvMsgFailure :: forall block point (query :: * -> *) (m :: * -> *) a.
ClientStAcquiring block point query m a
-> AcquireFailure -> m (ClientStIdle block point query m a)
recvMsgFailure } =
      ClientStAcquiring :: forall block point (query :: * -> *) (m :: * -> *) a.
m (ClientStAcquired block point query m a)
-> (AcquireFailure -> m (ClientStIdle block point query m a))
-> ClientStAcquiring block point query m a
ClientStAcquiring {
        recvMsgAcquired :: m (ClientStAcquired block' point' query' m a)
recvMsgAcquired = ClientStAcquired block point query m a
-> ClientStAcquired block' point' query' m a
goAcquired (ClientStAcquired block point query m a
 -> ClientStAcquired block' point' query' m a)
-> m (ClientStAcquired block point query m a)
-> m (ClientStAcquired block' point' query' m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (ClientStAcquired block point query m a)
recvMsgAcquired,
        recvMsgFailure :: AcquireFailure -> m (ClientStIdle block' point' query' m a)
recvMsgFailure  = \AcquireFailure
failure -> (ClientStIdle block point query m a
 -> ClientStIdle block' point' query' m a)
-> m (ClientStIdle block point query m a)
-> m (ClientStIdle block' point' query' m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ClientStIdle block point query m a
-> ClientStIdle block' point' query' m a
goIdle (AcquireFailure -> m (ClientStIdle block point query m a)
recvMsgFailure AcquireFailure
failure)
      }

    goAcquired :: ClientStAcquired block  point  query  m a
               -> ClientStAcquired block' point' query' m a
    goAcquired :: ClientStAcquired block point query m a
-> ClientStAcquired block' point' query' m a
goAcquired (SendMsgQuery     query result
q  ClientStQuerying block point query m a result
k) = case query result -> Some query'
forall result. query result -> Some query'
fquery query result
q of
                                           Some query' a
q' -> query' a
-> ClientStQuerying block' point' query' m a a
-> ClientStAcquired block' point' query' m a
forall (query :: * -> *) result block point (m :: * -> *) a.
query result
-> ClientStQuerying block point query m a result
-> ClientStAcquired block point query m a
SendMsgQuery query' a
q' (query result
-> query' a
-> ClientStQuerying block point query m a result
-> ClientStQuerying block' point' query' m a a
forall result result'.
query result
-> query' result'
-> ClientStQuerying block point query m a result
-> ClientStQuerying block' point' query' m a result'
goQuerying query result
q query' a
q' ClientStQuerying block point query m a result
k)
    goAcquired (SendMsgReAcquire Maybe point
pt ClientStAcquiring block point query m a
k) = Maybe point'
-> ClientStAcquiring block' point' query' m a
-> ClientStAcquired block' point' query' m a
forall point block (query :: * -> *) (m :: * -> *) a.
Maybe point
-> ClientStAcquiring block point query m a
-> ClientStAcquired block point query m a
SendMsgReAcquire (point -> point'
fpoint (point -> point') -> Maybe point -> Maybe point'
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe point
pt) (ClientStAcquiring block point query m a
-> ClientStAcquiring block' point' query' m a
goAcquiring ClientStAcquiring block point query m a
k)
    goAcquired (SendMsgRelease      m (ClientStIdle block point query m a)
k) = m (ClientStIdle block' point' query' m a)
-> ClientStAcquired block' point' query' m a
forall (m :: * -> *) block point (query :: * -> *) a.
m (ClientStIdle block point query m a)
-> ClientStAcquired block point query m a
SendMsgRelease ((ClientStIdle block point query m a
 -> ClientStIdle block' point' query' m a)
-> m (ClientStIdle block point query m a)
-> m (ClientStIdle block' point' query' m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ClientStIdle block point query m a
-> ClientStIdle block' point' query' m a
goIdle m (ClientStIdle block point query m a)
k)

    goQuerying :: forall result result'.
                  query  result
               -> query' result'
               -> ClientStQuerying block  point  query  m a result
               -> ClientStQuerying block' point' query' m a result'
    goQuerying :: query result
-> query' result'
-> ClientStQuerying block point query m a result
-> ClientStQuerying block' point' query' m a result'
goQuerying query result
q query' result'
q' ClientStQuerying {result -> m (ClientStAcquired block point query m a)
recvMsgResult :: result -> m (ClientStAcquired block point query m a)
recvMsgResult :: forall block point (query :: * -> *) (m :: * -> *) a result.
ClientStQuerying block point query m a result
-> result -> m (ClientStAcquired block point query m a)
recvMsgResult} =
      ClientStQuerying :: forall block point (query :: * -> *) (m :: * -> *) a result.
(result -> m (ClientStAcquired block point query m a))
-> ClientStQuerying block point query m a result
ClientStQuerying {
        recvMsgResult :: result' -> m (ClientStAcquired block' point' query' m a)
recvMsgResult = \result'
result' ->
          let result :: result
              result :: result
result = query result -> query' result' -> result' -> result
forall result result'.
query result -> query' result' -> result' -> result
fresult query result
q query' result'
q' result'
result' in
          (ClientStAcquired block point query m a
 -> ClientStAcquired block' point' query' m a)
-> m (ClientStAcquired block point query m a)
-> m (ClientStAcquired block' point' query' m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ClientStAcquired block point query m a
-> ClientStAcquired block' point' query' m a
goAcquired (result -> m (ClientStAcquired block point query m a)
recvMsgResult result
result)
      }


-- | Interpret a 'LocalStateQueryClient' action sequence as a 'Peer' on the
-- client side of the 'LocalStateQuery' protocol.
--
localStateQueryClientPeer
  :: forall block point (query :: Type -> Type) m a.
     Monad m
  => LocalStateQueryClient block point query m a
  -> Peer (LocalStateQuery block point query) AsClient StIdle m a
localStateQueryClientPeer :: LocalStateQueryClient block point query m a
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
localStateQueryClientPeer (LocalStateQueryClient m (ClientStIdle block point query m a)
handler) =
    m (Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a)
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (m (Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a)
 -> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a)
-> m (Peer
        (LocalStateQuery block point query) 'AsClient 'StIdle m a)
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
forall a b. (a -> b) -> a -> b
$ ClientStIdle block point query m a
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
handleStIdle (ClientStIdle block point query m a
 -> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a)
-> m (ClientStIdle block point query m a)
-> m (Peer
        (LocalStateQuery block point query) 'AsClient 'StIdle m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (ClientStIdle block point query m a)
handler
  where
    handleStIdle
      :: ClientStIdle block point query m a
      -> Peer (LocalStateQuery block point query) AsClient StIdle m a
    handleStIdle :: ClientStIdle block point query m a
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
handleStIdle ClientStIdle block point query m a
req = case ClientStIdle block point query m a
req of
      SendMsgAcquire Maybe point
pt ClientStAcquiring block point query m a
stAcquiring ->
        WeHaveAgency 'AsClient 'StIdle
-> Message (LocalStateQuery block point query) 'StIdle 'StAcquiring
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquiring m a
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StIdle -> WeHaveAgency 'AsClient 'StIdle
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StIdle
forall k k (block :: k) (point :: k) (query :: * -> *).
ClientHasAgency 'StIdle
TokIdle)
              (Maybe point
-> Message (LocalStateQuery block point query) 'StIdle 'StAcquiring
forall k point (block :: k) (query :: * -> *).
Maybe point
-> Message (LocalStateQuery block point query) 'StIdle 'StAcquiring
MsgAcquire Maybe point
pt)
              (ClientStAcquiring block point query m a
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquiring m a
handleStAcquiring ClientStAcquiring block point query m a
stAcquiring)
      SendMsgDone a
a ->
        WeHaveAgency 'AsClient 'StIdle
-> Message (LocalStateQuery block point query) 'StIdle 'StDone
-> Peer (LocalStateQuery block point query) 'AsClient 'StDone m a
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StIdle -> WeHaveAgency 'AsClient 'StIdle
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StIdle
forall k k (block :: k) (point :: k) (query :: * -> *).
ClientHasAgency 'StIdle
TokIdle)
              Message (LocalStateQuery block point query) 'StIdle 'StDone
forall k k (block :: k) (point :: k) (query :: * -> *).
Message (LocalStateQuery block point query) 'StIdle 'StDone
MsgDone
              (NobodyHasAgency 'StDone
-> a
-> Peer (LocalStateQuery block point query) 'AsClient 'StDone m a
forall ps (st :: ps) a (pr :: PeerRole) (m :: * -> *).
NobodyHasAgency st -> a -> Peer ps pr st m a
Done NobodyHasAgency 'StDone
forall k k (block :: k) (point :: k) (query :: * -> *).
NobodyHasAgency 'StDone
TokDone a
a)

    handleStAcquiring
      :: ClientStAcquiring block point query m a
      -> Peer (LocalStateQuery block point query) AsClient StAcquiring m a
    handleStAcquiring :: ClientStAcquiring block point query m a
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquiring m a
handleStAcquiring ClientStAcquiring{m (ClientStAcquired block point query m a)
recvMsgAcquired :: m (ClientStAcquired block point query m a)
recvMsgAcquired :: forall block point (query :: * -> *) (m :: * -> *) a.
ClientStAcquiring block point query m a
-> m (ClientStAcquired block point query m a)
recvMsgAcquired, AcquireFailure -> m (ClientStIdle block point query m a)
recvMsgFailure :: AcquireFailure -> m (ClientStIdle block point query m a)
recvMsgFailure :: forall block point (query :: * -> *) (m :: * -> *) a.
ClientStAcquiring block point query m a
-> AcquireFailure -> m (ClientStIdle block point query m a)
recvMsgFailure} =
      TheyHaveAgency 'AsClient 'StAcquiring
-> (forall (st' :: LocalStateQuery block point query).
    Message (LocalStateQuery block point query) 'StAcquiring st'
    -> Peer (LocalStateQuery block point query) 'AsClient st' m a)
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquiring m a
forall (pr :: PeerRole) ps (st :: ps) (m :: * -> *) a.
TheyHaveAgency pr st
-> (forall (st' :: ps). Message ps st st' -> Peer ps pr st' m a)
-> Peer ps pr st m a
Await (ServerHasAgency 'StAcquiring
-> PeerHasAgency 'AsServer 'StAcquiring
forall ps (st :: ps).
ServerHasAgency st -> PeerHasAgency 'AsServer st
ServerAgency ServerHasAgency 'StAcquiring
forall k k (block :: k) (point :: k) (query :: * -> *).
ServerHasAgency 'StAcquiring
TokAcquiring) ((forall (st' :: LocalStateQuery block point query).
  Message (LocalStateQuery block point query) 'StAcquiring st'
  -> Peer (LocalStateQuery block point query) 'AsClient st' m a)
 -> Peer
      (LocalStateQuery block point query) 'AsClient 'StAcquiring m a)
-> (forall (st' :: LocalStateQuery block point query).
    Message (LocalStateQuery block point query) 'StAcquiring st'
    -> Peer (LocalStateQuery block point query) 'AsClient st' m a)
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquiring m a
forall a b. (a -> b) -> a -> b
$ \Message (LocalStateQuery block point query) 'StAcquiring st'
req -> case Message (LocalStateQuery block point query) 'StAcquiring st'
req of
        Message (LocalStateQuery block point query) 'StAcquiring st'
MsgAcquired        -> m (Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquired m a)
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquired m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (m (Peer
      (LocalStateQuery block point query) 'AsClient 'StAcquired m a)
 -> Peer
      (LocalStateQuery block point query) 'AsClient 'StAcquired m a)
-> m (Peer
        (LocalStateQuery block point query) 'AsClient 'StAcquired m a)
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquired m a
forall a b. (a -> b) -> a -> b
$ ClientStAcquired block point query m a
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquired m a
handleStAcquired (ClientStAcquired block point query m a
 -> Peer
      (LocalStateQuery block point query) 'AsClient 'StAcquired m a)
-> m (ClientStAcquired block point query m a)
-> m (Peer
        (LocalStateQuery block point query) 'AsClient 'StAcquired m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (ClientStAcquired block point query m a)
recvMsgAcquired
        MsgFailure failure -> m (Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a)
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (m (Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a)
 -> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a)
-> m (Peer
        (LocalStateQuery block point query) 'AsClient 'StIdle m a)
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
forall a b. (a -> b) -> a -> b
$ ClientStIdle block point query m a
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
handleStIdle (ClientStIdle block point query m a
 -> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a)
-> m (ClientStIdle block point query m a)
-> m (Peer
        (LocalStateQuery block point query) 'AsClient 'StIdle m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AcquireFailure -> m (ClientStIdle block point query m a)
recvMsgFailure AcquireFailure
failure

    handleStAcquired
      :: ClientStAcquired block point query m a
      -> Peer (LocalStateQuery block point query) AsClient StAcquired m a
    handleStAcquired :: ClientStAcquired block point query m a
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquired m a
handleStAcquired ClientStAcquired block point query m a
req = case ClientStAcquired block point query m a
req of
      SendMsgQuery query result
query ClientStQuerying block point query m a result
stQuerying ->
        WeHaveAgency 'AsClient 'StAcquired
-> Message
     (LocalStateQuery block point query)
     'StAcquired
     ('StQuerying result)
-> Peer
     (LocalStateQuery block point query)
     'AsClient
     ('StQuerying result)
     m
     a
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquired m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StAcquired -> WeHaveAgency 'AsClient 'StAcquired
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StAcquired
forall k k (block :: k) (point :: k) (query :: * -> *).
ClientHasAgency 'StAcquired
TokAcquired)
              (query result
-> Message
     (LocalStateQuery block point query)
     'StAcquired
     ('StQuerying result)
forall k k (query :: * -> *) result (block :: k) (point :: k).
query result
-> Message
     (LocalStateQuery block point query)
     'StAcquired
     ('StQuerying result)
MsgQuery query result
query)
              (query result
-> ClientStQuerying block point query m a result
-> Peer
     (LocalStateQuery block point query)
     'AsClient
     ('StQuerying result)
     m
     a
forall result.
query result
-> ClientStQuerying block point query m a result
-> Peer
     (LocalStateQuery block point query)
     'AsClient
     ('StQuerying result)
     m
     a
handleStQuerying query result
query ClientStQuerying block point query m a result
stQuerying)
      SendMsgReAcquire Maybe point
pt ClientStAcquiring block point query m a
stAcquiring ->
        WeHaveAgency 'AsClient 'StAcquired
-> Message
     (LocalStateQuery block point query) 'StAcquired 'StAcquiring
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquiring m a
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquired m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StAcquired -> WeHaveAgency 'AsClient 'StAcquired
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StAcquired
forall k k (block :: k) (point :: k) (query :: * -> *).
ClientHasAgency 'StAcquired
TokAcquired)
              (Maybe point
-> Message
     (LocalStateQuery block point query) 'StAcquired 'StAcquiring
forall k point (block :: k) (query :: * -> *).
Maybe point
-> Message
     (LocalStateQuery block point query) 'StAcquired 'StAcquiring
MsgReAcquire Maybe point
pt)
              (ClientStAcquiring block point query m a
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquiring m a
handleStAcquiring ClientStAcquiring block point query m a
stAcquiring)
      SendMsgRelease m (ClientStIdle block point query m a)
stIdle ->
        WeHaveAgency 'AsClient 'StAcquired
-> Message (LocalStateQuery block point query) 'StAcquired 'StIdle
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquired m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StAcquired -> WeHaveAgency 'AsClient 'StAcquired
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StAcquired
forall k k (block :: k) (point :: k) (query :: * -> *).
ClientHasAgency 'StAcquired
TokAcquired)
              Message (LocalStateQuery block point query) 'StAcquired 'StIdle
forall k k (block :: k) (point :: k) (query :: * -> *).
Message (LocalStateQuery block point query) 'StAcquired 'StIdle
MsgRelease
              (m (Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a)
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (ClientStIdle block point query m a
-> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a
handleStIdle (ClientStIdle block point query m a
 -> Peer (LocalStateQuery block point query) 'AsClient 'StIdle m a)
-> m (ClientStIdle block point query m a)
-> m (Peer
        (LocalStateQuery block point query) 'AsClient 'StIdle m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (ClientStIdle block point query m a)
stIdle))

    handleStQuerying
      :: query result
      -> ClientStQuerying block point query m a result
      -> Peer (LocalStateQuery block point query) AsClient (StQuerying result) m a
    handleStQuerying :: query result
-> ClientStQuerying block point query m a result
-> Peer
     (LocalStateQuery block point query)
     'AsClient
     ('StQuerying result)
     m
     a
handleStQuerying query result
query ClientStQuerying{result -> m (ClientStAcquired block point query m a)
recvMsgResult :: result -> m (ClientStAcquired block point query m a)
recvMsgResult :: forall block point (query :: * -> *) (m :: * -> *) a result.
ClientStQuerying block point query m a result
-> result -> m (ClientStAcquired block point query m a)
recvMsgResult} =
      TheyHaveAgency 'AsClient ('StQuerying result)
-> (forall (st' :: LocalStateQuery block point query).
    Message
      (LocalStateQuery block point query) ('StQuerying result) st'
    -> Peer (LocalStateQuery block point query) 'AsClient st' m a)
-> Peer
     (LocalStateQuery block point query)
     'AsClient
     ('StQuerying result)
     m
     a
forall (pr :: PeerRole) ps (st :: ps) (m :: * -> *) a.
TheyHaveAgency pr st
-> (forall (st' :: ps). Message ps st st' -> Peer ps pr st' m a)
-> Peer ps pr st m a
Await (ServerHasAgency ('StQuerying result)
-> PeerHasAgency 'AsServer ('StQuerying result)
forall ps (st :: ps).
ServerHasAgency st -> PeerHasAgency 'AsServer st
ServerAgency (query result -> ServerHasAgency ('StQuerying result)
forall k k (query :: * -> *) result (block :: k) (point :: k).
query result -> ServerHasAgency ('StQuerying result)
TokQuerying query result
query)) ((forall (st' :: LocalStateQuery block point query).
  Message
    (LocalStateQuery block point query) ('StQuerying result) st'
  -> Peer (LocalStateQuery block point query) 'AsClient st' m a)
 -> Peer
      (LocalStateQuery block point query)
      'AsClient
      ('StQuerying result)
      m
      a)
-> (forall (st' :: LocalStateQuery block point query).
    Message
      (LocalStateQuery block point query) ('StQuerying result) st'
    -> Peer (LocalStateQuery block point query) 'AsClient st' m a)
-> Peer
     (LocalStateQuery block point query)
     'AsClient
     ('StQuerying result)
     m
     a
forall a b. (a -> b) -> a -> b
$ \Message
  (LocalStateQuery block point query) ('StQuerying result) st'
req -> case Message
  (LocalStateQuery block point query) ('StQuerying result) st'
req of
        MsgResult _ result -> m (Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquired m a)
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquired m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (ClientStAcquired block point query m a
-> Peer
     (LocalStateQuery block point query) 'AsClient 'StAcquired m a
handleStAcquired (ClientStAcquired block point query m a
 -> Peer
      (LocalStateQuery block point query) 'AsClient 'StAcquired m a)
-> m (ClientStAcquired block point query m a)
-> m (Peer
        (LocalStateQuery block point query) 'AsClient 'StAcquired m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> result -> m (ClientStAcquired block point query m a)
recvMsgResult result
result
result)