packages feed

swarm-0.7.0.0: src/swarm-engine/Swarm/Game/Popup.hs

{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TemplateHaskell #-}

module Swarm.Game.Popup (
  -- * Popup types
  Popup (..),

  -- * Popup state
  PopupState,
  currentPopup,
  popupQueue,
  initPopupState,
  addPopup,
  nextPopup,
) where

import Control.Lens (makeLenses, use, (%~), (.=))
import Control.Monad.State (MonadState)
import Data.Sequence (Seq, (|>), pattern (:<|))
import Data.Sequence qualified as Seq
import Swarm.Game.Achievement.Definitions (CategorizedAchievement)
import Swarm.Language.Syntax (Const)

-- | Different types of popups that can be displayed to the
--   player.
data Popup
  = AchievementPopup CategorizedAchievement
  | RecipesPopup
  | CommandsPopup [Const]
  | DebugWarningPopup

-- | State to track pending popup queue as well as any
--   popup which is currently being displayed.
data PopupState = PopupState
  { _currentPopup :: Maybe Popup
  , _popupQueue :: Seq Popup
  }

makeLenses ''PopupState

-- | Initial, empty popup state.
initPopupState :: PopupState
initPopupState =
  PopupState
    { _currentPopup = Nothing
    , _popupQueue = Seq.empty
    }

-- | Add a popup to the end of the queue.
addPopup :: Popup -> PopupState -> PopupState
addPopup notif = popupQueue %~ (|> notif)

-- | Move the next popup (if any) from the queue to the
--   currently displayed popup.
nextPopup :: MonadState PopupState m => m ()
nextPopup = do
  q <- use popupQueue
  case q of
    Seq.Empty -> currentPopup .= Nothing
    n :<| ns -> do
      currentPopup .= Just n
      popupQueue .= ns