-- |
-- SPDX-License-Identifier: BSD-3-Clause
--
-- Collection of helper functions for managing achievements in other controllers.
module Swarm.TUI.Model.Achievements (
  attainAchievement,
  attainAchievement',
  popupAchievement,
) where

import Brick (EventM)
import Control.Lens hiding (from, (<.>))
import Control.Monad (when)
import Control.Monad.IO.Class (MonadIO (liftIO))
import Control.Monad.State (MonadState)
import Data.Map qualified as M
import Data.Maybe (isNothing)
import Data.Time (ZonedTime, getZonedTime)
import Swarm.Game.Achievement.Attainment
import Swarm.Game.Achievement.Definitions
import Swarm.Game.Achievement.Persistence
import Swarm.Game.Popup (Popup (AchievementPopup), addPopup)
import Swarm.Game.Scenario.Status (ScenarioPath (..))
import Swarm.TUI.Model

attainAchievement ::
  CategorizedAchievement ->
  EventM n ProgressionState ()
attainAchievement :: forall n. CategorizedAchievement -> EventM n ProgressionState ()
attainAchievement CategorizedAchievement
a = do
  ZonedTime
currentTime <- IO ZonedTime -> EventM n ProgressionState ZonedTime
forall a. IO a -> EventM n ProgressionState a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ZonedTime
getZonedTime
  ZonedTime
-> Maybe ScenarioPath
-> CategorizedAchievement
-> EventM n ProgressionState ()
forall n.
ZonedTime
-> Maybe ScenarioPath
-> CategorizedAchievement
-> EventM n ProgressionState ()
attainAchievement' ZonedTime
currentTime Maybe ScenarioPath
forall a. Maybe a
Nothing CategorizedAchievement
a

attainAchievement' ::
  ZonedTime ->
  Maybe ScenarioPath ->
  CategorizedAchievement ->
  EventM n ProgressionState ()
attainAchievement' :: forall n.
ZonedTime
-> Maybe ScenarioPath
-> CategorizedAchievement
-> EventM n ProgressionState ()
attainAchievement' ZonedTime
t Maybe ScenarioPath
p CategorizedAchievement
a = do
  Maybe Attainment
mAttainment <- Getting (Maybe Attainment) ProgressionState (Maybe Attainment)
-> EventM n ProgressionState (Maybe Attainment)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting (Maybe Attainment) ProgressionState (Maybe Attainment)
 -> EventM n ProgressionState (Maybe Attainment))
-> Getting (Maybe Attainment) ProgressionState (Maybe Attainment)
-> EventM n ProgressionState (Maybe Attainment)
forall a b. (a -> b) -> a -> b
$ (Map CategorizedAchievement Attainment
 -> Const
      (Maybe Attainment) (Map CategorizedAchievement Attainment))
-> ProgressionState -> Const (Maybe Attainment) ProgressionState
Lens' ProgressionState (Map CategorizedAchievement Attainment)
attainedAchievements ((Map CategorizedAchievement Attainment
  -> Const
       (Maybe Attainment) (Map CategorizedAchievement Attainment))
 -> ProgressionState -> Const (Maybe Attainment) ProgressionState)
-> ((Maybe Attainment
     -> Const (Maybe Attainment) (Maybe Attainment))
    -> Map CategorizedAchievement Attainment
    -> Const
         (Maybe Attainment) (Map CategorizedAchievement Attainment))
-> Getting (Maybe Attainment) ProgressionState (Maybe Attainment)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (Map CategorizedAchievement Attainment)
-> Lens'
     (Map CategorizedAchievement Attainment)
     (Maybe (IxValue (Map CategorizedAchievement Attainment)))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at Index (Map CategorizedAchievement Attainment)
CategorizedAchievement
a
  Bool
-> EventM n ProgressionState () -> EventM n ProgressionState ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe Attainment -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Attainment
mAttainment) (EventM n ProgressionState () -> EventM n ProgressionState ())
-> EventM n ProgressionState () -> EventM n ProgressionState ()
forall a b. (a -> b) -> a -> b
$ CategorizedAchievement -> EventM n ProgressionState ()
forall (m :: * -> *).
MonadState ProgressionState m =>
CategorizedAchievement -> m ()
popupAchievement CategorizedAchievement
a

  (Map CategorizedAchievement Attainment
 -> Identity (Map CategorizedAchievement Attainment))
-> ProgressionState -> Identity ProgressionState
Lens' ProgressionState (Map CategorizedAchievement Attainment)
attainedAchievements
    ((Map CategorizedAchievement Attainment
  -> Identity (Map CategorizedAchievement Attainment))
 -> ProgressionState -> Identity ProgressionState)
-> (Map CategorizedAchievement Attainment
    -> Map CategorizedAchievement Attainment)
-> EventM n ProgressionState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= (Attainment -> Attainment -> Attainment)
-> CategorizedAchievement
-> Attainment
-> Map CategorizedAchievement Attainment
-> Map CategorizedAchievement Attainment
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
M.insertWith
      Attainment -> Attainment -> Attainment
forall a. Semigroup a => a -> a -> a
(<>)
      CategorizedAchievement
a
      (CategorizedAchievement -> Maybe FilePath -> ZonedTime -> Attainment
Attainment CategorizedAchievement
a (ScenarioPath -> FilePath
getScenarioPath (ScenarioPath -> FilePath) -> Maybe ScenarioPath -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe ScenarioPath
p) ZonedTime
t)
  Map CategorizedAchievement Attainment
newAchievements <- Getting
  (Map CategorizedAchievement Attainment)
  ProgressionState
  (Map CategorizedAchievement Attainment)
-> EventM
     n ProgressionState (Map CategorizedAchievement Attainment)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting
  (Map CategorizedAchievement Attainment)
  ProgressionState
  (Map CategorizedAchievement Attainment)
Lens' ProgressionState (Map CategorizedAchievement Attainment)
attainedAchievements
  IO () -> EventM n ProgressionState ()
forall a. IO a -> EventM n ProgressionState a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> EventM n ProgressionState ())
-> IO () -> EventM n ProgressionState ()
forall a b. (a -> b) -> a -> b
$ [Attainment] -> IO ()
saveAchievementsInfo ([Attainment] -> IO ()) -> [Attainment] -> IO ()
forall a b. (a -> b) -> a -> b
$ Map CategorizedAchievement Attainment -> [Attainment]
forall k a. Map k a -> [a]
M.elems Map CategorizedAchievement Attainment
newAchievements

-- | Generate a popup for an achievement.
popupAchievement :: MonadState ProgressionState m => CategorizedAchievement -> m ()
popupAchievement :: forall (m :: * -> *).
MonadState ProgressionState m =>
CategorizedAchievement -> m ()
popupAchievement CategorizedAchievement
ach = (PopupState -> Identity PopupState)
-> ProgressionState -> Identity ProgressionState
Lens' ProgressionState PopupState
uiPopups ((PopupState -> Identity PopupState)
 -> ProgressionState -> Identity ProgressionState)
-> (PopupState -> PopupState) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= Popup -> PopupState -> PopupState
addPopup (CategorizedAchievement -> Popup
AchievementPopup CategorizedAchievement
ach)