-- |
-- 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 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.TUI.Model
import Swarm.TUI.Model.Popup (Popup (AchievementPopup), addPopup)
import Swarm.TUI.Model.UI

attainAchievement :: (MonadIO m, MonadState AppState m) => CategorizedAchievement -> m ()
attainAchievement :: forall (m :: * -> *).
(MonadIO m, MonadState AppState m) =>
CategorizedAchievement -> m ()
attainAchievement CategorizedAchievement
a = do
  ZonedTime
currentTime <- IO ZonedTime -> m ZonedTime
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ZonedTime
getZonedTime
  ZonedTime -> Maybe FilePath -> CategorizedAchievement -> m ()
forall (m :: * -> *).
(MonadIO m, MonadState AppState m) =>
ZonedTime -> Maybe FilePath -> CategorizedAchievement -> m ()
attainAchievement' ZonedTime
currentTime Maybe FilePath
forall a. Maybe a
Nothing CategorizedAchievement
a

attainAchievement' ::
  (MonadIO m, MonadState AppState m) =>
  ZonedTime ->
  Maybe FilePath ->
  CategorizedAchievement ->
  m ()
attainAchievement' :: forall (m :: * -> *).
(MonadIO m, MonadState AppState m) =>
ZonedTime -> Maybe FilePath -> CategorizedAchievement -> m ()
attainAchievement' ZonedTime
t Maybe FilePath
p CategorizedAchievement
a = do
  Maybe Attainment
mAttainment <- Getting (Maybe Attainment) AppState (Maybe Attainment)
-> m (Maybe Attainment)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting (Maybe Attainment) AppState (Maybe Attainment)
 -> m (Maybe Attainment))
-> Getting (Maybe Attainment) AppState (Maybe Attainment)
-> m (Maybe Attainment)
forall a b. (a -> b) -> a -> b
$ (UIState -> Const (Maybe Attainment) UIState)
-> AppState -> Const (Maybe Attainment) AppState
Lens' AppState UIState
uiState ((UIState -> Const (Maybe Attainment) UIState)
 -> AppState -> Const (Maybe Attainment) AppState)
-> ((Maybe Attainment
     -> Const (Maybe Attainment) (Maybe Attainment))
    -> UIState -> Const (Maybe Attainment) UIState)
-> Getting (Maybe Attainment) AppState (Maybe Attainment)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map CategorizedAchievement Attainment
 -> Const
      (Maybe Attainment) (Map CategorizedAchievement Attainment))
-> UIState -> Const (Maybe Attainment) UIState
Lens' UIState (Map CategorizedAchievement Attainment)
uiAchievements ((Map CategorizedAchievement Attainment
  -> Const
       (Maybe Attainment) (Map CategorizedAchievement Attainment))
 -> UIState -> Const (Maybe Attainment) UIState)
-> ((Maybe Attainment
     -> Const (Maybe Attainment) (Maybe Attainment))
    -> Map CategorizedAchievement Attainment
    -> Const
         (Maybe Attainment) (Map CategorizedAchievement Attainment))
-> (Maybe Attainment
    -> Const (Maybe Attainment) (Maybe Attainment))
-> UIState
-> Const (Maybe Attainment) UIState
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 -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe Attainment -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Attainment
mAttainment) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ CategorizedAchievement -> m ()
forall (m :: * -> *).
MonadState AppState m =>
CategorizedAchievement -> m ()
popupAchievement CategorizedAchievement
a

  ((UIState -> Identity UIState) -> AppState -> Identity AppState
Lens' AppState UIState
uiState ((UIState -> Identity UIState) -> AppState -> Identity AppState)
-> ((Map CategorizedAchievement Attainment
     -> Identity (Map CategorizedAchievement Attainment))
    -> UIState -> Identity UIState)
-> (Map CategorizedAchievement Attainment
    -> Identity (Map CategorizedAchievement Attainment))
-> AppState
-> Identity AppState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map CategorizedAchievement Attainment
 -> Identity (Map CategorizedAchievement Attainment))
-> UIState -> Identity UIState
Lens' UIState (Map CategorizedAchievement Attainment)
uiAchievements)
    ((Map CategorizedAchievement Attainment
  -> Identity (Map CategorizedAchievement Attainment))
 -> AppState -> Identity AppState)
-> (Map CategorizedAchievement Attainment
    -> Map CategorizedAchievement Attainment)
-> m ()
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 Maybe FilePath
p ZonedTime
t)
  Map CategorizedAchievement Attainment
newAchievements <- Getting
  (Map CategorizedAchievement Attainment)
  AppState
  (Map CategorizedAchievement Attainment)
-> m (Map CategorizedAchievement Attainment)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting
   (Map CategorizedAchievement Attainment)
   AppState
   (Map CategorizedAchievement Attainment)
 -> m (Map CategorizedAchievement Attainment))
-> Getting
     (Map CategorizedAchievement Attainment)
     AppState
     (Map CategorizedAchievement Attainment)
-> m (Map CategorizedAchievement Attainment)
forall a b. (a -> b) -> a -> b
$ (UIState -> Const (Map CategorizedAchievement Attainment) UIState)
-> AppState
-> Const (Map CategorizedAchievement Attainment) AppState
Lens' AppState UIState
uiState ((UIState -> Const (Map CategorizedAchievement Attainment) UIState)
 -> AppState
 -> Const (Map CategorizedAchievement Attainment) AppState)
-> ((Map CategorizedAchievement Attainment
     -> Const
          (Map CategorizedAchievement Attainment)
          (Map CategorizedAchievement Attainment))
    -> UIState
    -> Const (Map CategorizedAchievement Attainment) UIState)
-> Getting
     (Map CategorizedAchievement Attainment)
     AppState
     (Map CategorizedAchievement Attainment)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map CategorizedAchievement Attainment
 -> Const
      (Map CategorizedAchievement Attainment)
      (Map CategorizedAchievement Attainment))
-> UIState -> Const (Map CategorizedAchievement Attainment) UIState
Lens' UIState (Map CategorizedAchievement Attainment)
uiAchievements
  IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
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 AppState m => CategorizedAchievement -> m ()
popupAchievement :: forall (m :: * -> *).
MonadState AppState m =>
CategorizedAchievement -> m ()
popupAchievement CategorizedAchievement
ach = (UIState -> Identity UIState) -> AppState -> Identity AppState
Lens' AppState UIState
uiState ((UIState -> Identity UIState) -> AppState -> Identity AppState)
-> ((PopupState -> Identity PopupState)
    -> UIState -> Identity UIState)
-> (PopupState -> Identity PopupState)
-> AppState
-> Identity AppState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PopupState -> Identity PopupState) -> UIState -> Identity UIState
Lens' UIState PopupState
uiPopups ((PopupState -> Identity PopupState)
 -> AppState -> Identity AppState)
-> (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)