module Tendermint.SDK.BaseApp.Store.Var
  ( Var
  , makeVar
  , makeFullStoreKey
  , takeVar
  , unsafeTakeVar
  , putVar
  , deleteVar
  ) where

import           Control.Lens                          ((^.))
import           Data.Kind                             (Type)
import           Polysemy                              (Member, Members, Sem)
import           Polysemy.Error                        (Error)
import           Tendermint.SDK.BaseApp.Errors         (AppError,
                                                        SDKError (StoreError),
                                                        throwSDKError)
import qualified Tendermint.SDK.BaseApp.Store.RawStore as S
import           Tendermint.SDK.Codec                  (HasCodec (..))

data Var (a :: Type) = Var
  { Var a -> Store (Var a)
varStore :: S.Store (Var a) }

instance S.IsKey () (Var a) where
    type Value () (Var a) = a

makeVar
  :: S.IsKey k ns
  => S.Value k ns ~ Var a
  => k
  -> S.Store ns
  -> S.Value k ns
makeVar :: k -> Store ns -> Value k ns
makeVar key :: k
key store :: Store ns
store =
  Store (Var a) -> Value k ns
forall a. Store (Var a) -> Var a
Var (Store (Var a) -> Value k ns) -> Store (Var a) -> Value k ns
forall a b. (a -> b) -> a -> b
$ Store ns -> Store (Var a) -> Store (Var a)
forall k1 k2 (parentns :: k1) (childns :: k2).
Store parentns -> Store childns -> Store childns
S.nestStore Store ns
store (Store (Var a) -> Store (Var a)) -> Store (Var a) -> Store (Var a)
forall a b. (a -> b) -> a -> b
$
    KeyRoot (Var a) -> Store (Var a)
forall k (ns :: k). KeyRoot ns -> Store ns
S.makeStore (KeyRoot (Var a) -> Store (Var a))
-> (ByteString -> KeyRoot (Var a)) -> ByteString -> Store (Var a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> KeyRoot (Var a)
forall k (ns :: k). ByteString -> KeyRoot ns
S.KeyRoot (ByteString -> Store (Var a)) -> ByteString -> Store (Var a)
forall a b. (a -> b) -> a -> b
$ k
key k -> Getting ByteString k ByteString -> ByteString
forall s a. s -> Getting a s a -> a
^. Getting ByteString k ByteString
forall k. RawKey k => Iso' k ByteString
S.rawKey

makeFullStoreKey
  :: Var a
  -> S.StoreKey
makeFullStoreKey :: Var a -> StoreKey
makeFullStoreKey Var{..} =
  Store (Var a) -> () -> StoreKey
forall k1 k2 (ns :: k1). IsKey k2 ns => Store ns -> k2 -> StoreKey
S.makeStoreKey Store (Var a)
varStore ()

takeVar
  :: Members [S.ReadStore, Error AppError] r
  => HasCodec a
  => Var a
  -> Sem r (Maybe a)
takeVar :: Var a -> Sem r (Maybe a)
takeVar Var{..} = Store (Var a) -> () -> Sem r (Maybe (Value () (Var a)))
forall k1 k2 (r :: [(* -> *) -> * -> *]) (ns :: k1).
(IsKey k2 ns, HasCodec (Value k2 ns),
 Members '[ReadStore, Error AppError] r) =>
Store ns -> k2 -> Sem r (Maybe (Value k2 ns))
S.get Store (Var a)
varStore ()

unsafeTakeVar
  :: Members [S.ReadStore, Error AppError] r
  => HasCodec a
  => Var a
  -> Sem r a
unsafeTakeVar :: Var a -> Sem r a
unsafeTakeVar Var{..} = do
  Maybe a
mRes <- Store (Var a) -> () -> Sem r (Maybe (Value () (Var a)))
forall k1 k2 (r :: [(* -> *) -> * -> *]) (ns :: k1).
(IsKey k2 ns, HasCodec (Value k2 ns),
 Members '[ReadStore, Error AppError] r) =>
Store ns -> k2 -> Sem r (Maybe (Value k2 ns))
S.get Store (Var a)
varStore ()
  case Maybe a
mRes of
    Just a :: a
a  -> a -> Sem r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a
    Nothing -> SDKError -> Sem r a
forall (r :: [(* -> *) -> * -> *]) a.
Member (Error AppError) r =>
SDKError -> Sem r a
throwSDKError (SDKError -> Sem r a) -> SDKError -> Sem r a
forall a b. (a -> b) -> a -> b
$ Text -> SDKError
StoreError "Var key not found."

putVar
  :: Member S.WriteStore r
  => HasCodec a
  => a
  -> Var a
  -> Sem r ()
putVar :: a -> Var a -> Sem r ()
putVar a :: a
a Var{..} = Store (Var a) -> () -> Value () (Var a) -> Sem r ()
forall k1 k2 (r :: [(* -> *) -> * -> *]) (ns :: k1).
(IsKey k2 ns, HasCodec (Value k2 ns), Member WriteStore r) =>
Store ns -> k2 -> Value k2 ns -> Sem r ()
S.put Store (Var a)
varStore () a
Value () (Var a)
a

deleteVar
  :: Member S.WriteStore r
  => Var a
  -> Sem r ()
deleteVar :: Var a -> Sem r ()
deleteVar Var{..} = Store (Var a) -> () -> Sem r ()
forall k1 k2 (ns :: k1) (r :: [(* -> *) -> * -> *]).
(IsKey k2 ns, Member WriteStore r) =>
Store ns -> k2 -> Sem r ()
S.delete Store (Var a)
varStore ()