content: {-# LANGUAGE DeriveAnyClass #-}
  {-# LANGUAGE DeriveGeneric #-}
  {-# LANGUAGE RankNTypes #-}
  
  module Server.ServerState
    ( ServerState (..),
      Channel (..),
      Content (..),
      MEvent,
      new,
      readResults,
      readPublisher,
      saveResults,
      savePublisher,
    )
  where
  
  import Control.Monad.IO.Unlift
  import Data.Hashable (Hashable)
  import Data.IORef (IORef, atomicModifyIORef, newIORef, readIORef, writeIORef)
  import Data.Morpheus.Subscriptions (Event (..), PubApp)
  import GHC.Generics
  
  data Channel
    = ChannelCounter
    deriving (Show, Eq, Generic, Hashable)
  
  newtype Content
    = Count Int
    deriving (Show)
  
  type MEvent = Event Channel Content
  
  data ServerState = ServerState
    { publisher :: IORef (MEvent -> IO ()),
      counter :: IORef Int
    }
  
  new :: IO ServerState
  new = do
    initCounter <- newIORef 0
    initPublisher <- newIORef $ \_ -> return () -- Initially, NOP
    return
      $ ServerState
        { counter = initCounter,
          publisher = initPublisher
        }
  
  readResults :: ServerState -> IO Int
  readResults ss =
    readIORef $ counter ss
  
  saveResults :: ServerState -> Int -> IO ()
  saveResults ss =
    writeIORef (counter ss)
  
  savePublisher :: ServerState -> (MEvent -> IO ()) -> IO ()
  savePublisher ss =
    writeIORef (publisher ss)
  
  readPublisher :: ServerState -> IO (MEvent -> IO ())
  readPublisher ss =
    readIORef $ publisher ss
  