{-# LANGUAGE RankNTypes #-}

{- |
Module      : Singular.Registry.Trie
Description : Per-token MPF trie management interface
License     : Apache-2.0

Record-of-functions interface for managing
per-token Merkle Patricia Forestry tries. The
'TrieManager' mediates access to individual 'Trie'
handles and provides speculative (read-your-writes,
then-discard) sessions for transaction building.
-}
module Singular.Registry.Trie
    ( -- * Trie manager
      TrieManager (..)

      -- * Single trie operations
    , Trie (..)
    ) where

import Data.ByteString (ByteString)

import Singular.Registry.Ledger (Root, TokenId)
import Singular.Registry.Types (ProofStep)

-- | Manager for per-token tries.
data TrieManager m = TrieManager
    { forall (m :: * -> *).
TrieManager m -> forall a. TokenId -> (Trie m -> m a) -> m a
withTrie
        :: forall a
         . TokenId
        -> (Trie m -> m a)
        -> m a
    -- ^ Run an action with access to a token's trie
    , forall (m :: * -> *).
TrieManager m
-> forall a.
   TokenId -> (forall (n :: * -> *). Monad n => Trie n -> n a) -> m a
withSpeculativeTrie
        :: forall a
         . TokenId
        -> ( forall n
              . (Monad n)
             => Trie n
             -> n a
           )
        -> m a
    {- ^ Run a read-your-writes session whose
    mutations are discarded at the end.
    -}
    , forall (m :: * -> *). TrieManager m -> TokenId -> m ()
createTrie :: TokenId -> m ()
    -- ^ Create a new empty trie for a token
    , forall (m :: * -> *). TrieManager m -> TokenId -> m ()
deleteTrie :: TokenId -> m ()
    -- ^ Delete a token's trie (permanent removal)
    , forall (m :: * -> *). TrieManager m -> TokenId -> m ()
hideTrie :: TokenId -> m ()
    -- ^ Mark a token's trie as hidden
    , forall (m :: * -> *). TrieManager m -> TokenId -> m ()
unhideTrie :: TokenId -> m ()
    -- ^ Restore a hidden token's trie
    }

-- | Operations on a single trie.
data Trie m = Trie
    { forall (m :: * -> *). Trie m -> ByteString -> ByteString -> m Root
insert
        :: ByteString -> ByteString -> m Root
    -- ^ Insert a key-value pair, returning new root
    , forall (m :: * -> *). Trie m -> ByteString -> m Root
delete :: ByteString -> m Root
    -- ^ Delete a key, returning new root
    , forall (m :: * -> *). Trie m -> ByteString -> m (Maybe ByteString)
lookup :: ByteString -> m (Maybe ByteString)
    -- ^ Look up a value by key
    , forall (m :: * -> *). Trie m -> m Root
getRoot :: m Root
    -- ^ Get current root hash
    , forall (m :: * -> *). Trie m -> ByteString -> m (Maybe [ProofStep])
getProofSteps
        :: ByteString -> m (Maybe [ProofStep])
    -- ^ Generate on-chain proof steps for a key
    }