module Cardano.Tracing.Kernel
  ( NodeKernelData (..)
  , mkNodeKernelData
  , setNodeKernel
  , mapNodeKernelDataIO
  -- * Re-exports
  , NodeKernel (..)
  , LocalConnectionId
  , RemoteConnectionId
  , StrictMaybe(..)
  , fromSMaybe
  ) where

import           Cardano.Prelude hiding (atomically)

import           Data.IORef (IORef, newIORef, readIORef, writeIORef)
import           Shelley.Spec.Ledger.BaseTypes (StrictMaybe (..), fromSMaybe)

import           Ouroboros.Consensus.Node (NodeKernel (..))
import           Ouroboros.Consensus.Util.Orphans ()

import           Ouroboros.Network.NodeToClient (LocalConnectionId)
import           Ouroboros.Network.NodeToNode (RemoteConnectionId)


newtype NodeKernelData blk =
  NodeKernelData
  { NodeKernelData blk
-> IORef
     (StrictMaybe
        (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
unNodeKernelData :: IORef (StrictMaybe (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
  }

mkNodeKernelData :: IO (NodeKernelData blk)
mkNodeKernelData :: IO (NodeKernelData blk)
mkNodeKernelData = IORef
  (StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
-> NodeKernelData blk
forall blk.
IORef
  (StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
-> NodeKernelData blk
NodeKernelData (IORef
   (StrictMaybe
      (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
 -> NodeKernelData blk)
-> IO
     (IORef
        (StrictMaybe
           (NodeKernel IO RemoteConnectionId LocalConnectionId blk)))
-> IO (NodeKernelData blk)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StrictMaybe
  (NodeKernel IO RemoteConnectionId LocalConnectionId blk)
-> IO
     (IORef
        (StrictMaybe
           (NodeKernel IO RemoteConnectionId LocalConnectionId blk)))
forall a. a -> IO (IORef a)
newIORef StrictMaybe
  (NodeKernel IO RemoteConnectionId LocalConnectionId blk)
forall a. StrictMaybe a
SNothing

setNodeKernel :: NodeKernelData blk
              -> NodeKernel IO RemoteConnectionId LocalConnectionId blk
              -> IO ()
setNodeKernel :: NodeKernelData blk
-> NodeKernel IO RemoteConnectionId LocalConnectionId blk -> IO ()
setNodeKernel (NodeKernelData IORef
  (StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
ref) NodeKernel IO RemoteConnectionId LocalConnectionId blk
nodeKern =
  IORef
  (StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
-> StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk)
-> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef
  (StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
ref (StrictMaybe
   (NodeKernel IO RemoteConnectionId LocalConnectionId blk)
 -> IO ())
-> StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk)
-> IO ()
forall a b. (a -> b) -> a -> b
$ NodeKernel IO RemoteConnectionId LocalConnectionId blk
-> StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk)
forall a. a -> StrictMaybe a
SJust NodeKernel IO RemoteConnectionId LocalConnectionId blk
nodeKern

mapNodeKernelDataIO ::
  (NodeKernel IO RemoteConnectionId LocalConnectionId blk -> IO a)
  -> NodeKernelData blk
  -> IO (StrictMaybe a)
mapNodeKernelDataIO :: (NodeKernel IO RemoteConnectionId LocalConnectionId blk -> IO a)
-> NodeKernelData blk -> IO (StrictMaybe a)
mapNodeKernelDataIO NodeKernel IO RemoteConnectionId LocalConnectionId blk -> IO a
f (NodeKernelData IORef
  (StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
ref) =
  IORef
  (StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
-> IO
     (StrictMaybe
        (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
forall a. IORef a -> IO a
readIORef IORef
  (StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
ref IO
  (StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk))
-> (StrictMaybe
      (NodeKernel IO RemoteConnectionId LocalConnectionId blk)
    -> IO (StrictMaybe a))
-> IO (StrictMaybe a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (NodeKernel IO RemoteConnectionId LocalConnectionId blk -> IO a)
-> StrictMaybe
     (NodeKernel IO RemoteConnectionId LocalConnectionId blk)
-> IO (StrictMaybe a)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse NodeKernel IO RemoteConnectionId LocalConnectionId blk -> IO a
f