{-# LANGUAGE OverloadedStrings #-}

-- |
-- SPDX-License-Identifier: BSD-3-Clause
module Swarm.TUI.View.Achievement where

import Brick
import Brick.Widgets.Border (borderWithLabel)
import Brick.Widgets.Center (hCenter)
import Brick.Widgets.List qualified as BL
import Control.Lens ((^.))
import Data.Map (Map)
import Data.Map qualified as M
import Data.Time.Format (defaultTimeLocale, formatTime)
import Swarm.Game.Achievement.Attainment
import Swarm.Game.Achievement.Definitions
import Swarm.Game.Achievement.Description
import Swarm.TUI.Model
import Swarm.TUI.Model.UI
import Swarm.TUI.View.Attribute.Attr
import Swarm.TUI.View.Util (drawMarkdown)
import Text.Wrap

padAllEvenly :: Int -> Widget Name -> Widget Name
padAllEvenly :: Int -> Widget Name -> Widget Name
padAllEvenly Int
x Widget Name
w = forall n. Int -> Widget n -> Widget n
padTopBottom Int
x forall a b. (a -> b) -> a -> b
$ forall n. Int -> Widget n -> Widget n
padLeftRight (Int
2 forall a. Num a => a -> a -> a
* Int
x) Widget Name
w

getCompletionIcon :: Bool -> Widget Name
getCompletionIcon :: Bool -> Widget Name
getCompletionIcon = \case
  Bool
False -> forall n. Text -> Widget n
txt Text
" ○  "
  Bool
True -> forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
greenAttr forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
" ●  "

drawAchievementsMenuUI :: AppState -> BL.List Name CategorizedAchievement -> Widget Name
drawAchievementsMenuUI :: AppState -> List Name CategorizedAchievement -> Widget Name
drawAchievementsMenuUI AppState
s List Name CategorizedAchievement
l =
  forall n. [Widget n] -> Widget n
vBox
    [ forall n. Widget n -> Widget n
hCenter forall a b. (a -> b) -> a -> b
$ forall n. Int -> Widget n -> Widget n
padTopBottom Int
1 forall a b. (a -> b) -> a -> b
$ forall n. String -> Widget n
str String
"🏆  Achievements 🏆 "
    , forall n. Widget n -> Widget n
hCenter forall a b. (a -> b) -> a -> b
$
        forall n. [Widget n] -> Widget n
hBox
          [ forall n. Int -> Widget n -> Widget n
hLimitPercent Int
30 forall a b. (a -> b) -> a -> b
$
              forall n. Int -> Widget n -> Widget n
padAll Int
2 forall a b. (a -> b) -> a -> b
$
                forall (t :: * -> *) n e.
(Traversable t, Splittable t, Ord n, Show n) =>
(Bool -> e -> Widget n) -> Bool -> GenericList n t e -> Widget n
BL.renderList (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ Map CategorizedAchievement Attainment
-> CategorizedAchievement -> Widget Name
drawAchievementListItem Map CategorizedAchievement Attainment
attainedMap) Bool
True List Name CategorizedAchievement
l
          , forall n. Int -> Widget n -> Widget n
hLimitPercent Int
50 forall a b. (a -> b) -> a -> b
$
              forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall n. Widget n
emptyWidget (Map CategorizedAchievement Attainment
-> CategorizedAchievement -> Widget Name
singleAchievementDetails Map CategorizedAchievement Attainment
attainedMap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd) forall a b. (a -> b) -> a -> b
$
                forall (t :: * -> *) e n.
(Splittable t, Traversable t, Semigroup (t e)) =>
GenericList n t e -> Maybe (Int, e)
BL.listSelectedElement List Name CategorizedAchievement
l
          ]
    ]
 where
  attainedMap :: Map CategorizedAchievement Attainment
attainedMap = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState (Map CategorizedAchievement Attainment)
uiAchievements

drawAchievementListItem ::
  Map CategorizedAchievement Attainment ->
  CategorizedAchievement ->
  Widget Name
drawAchievementListItem :: Map CategorizedAchievement Attainment
-> CategorizedAchievement -> Widget Name
drawAchievementListItem Map CategorizedAchievement Attainment
attainedMap CategorizedAchievement
x =
  Bool -> Widget Name
getCompletionIcon Bool
wasAttained forall n. Widget n -> Widget n -> Widget n
<+> forall n. Widget n
titleWidget
 where
  wasAttained :: Bool
wasAttained = forall k a. Ord k => k -> Map k a -> Bool
M.member CategorizedAchievement
x Map CategorizedAchievement Attainment
attainedMap
  titleWidget :: Widget n
titleWidget = forall n. Text -> Widget n
txtWrap forall a b. (a -> b) -> a -> b
$ AchievementInfo -> Text
title AchievementInfo
details
  details :: AchievementInfo
details = CategorizedAchievement -> AchievementInfo
describe CategorizedAchievement
x

singleAchievementDetails ::
  Map CategorizedAchievement Attainment ->
  CategorizedAchievement ->
  Widget Name
singleAchievementDetails :: Map CategorizedAchievement Attainment
-> CategorizedAchievement -> Widget Name
singleAchievementDetails Map CategorizedAchievement Attainment
attainedMap CategorizedAchievement
x =
  forall n. Padding -> Widget n -> Widget n
padRight (Int -> Padding
Pad Int
1) forall a b. (a -> b) -> a -> b
$ forall n. Widget n -> Widget n -> Widget n
borderWithLabel forall n. Widget n
titleWidget forall a b. (a -> b) -> a -> b
$ Int -> Widget Name -> Widget Name
padAllEvenly Int
1 Widget Name
innerContent
 where
  wasAttained :: Bool
wasAttained = forall k a. Ord k => k -> Map k a -> Bool
M.member CategorizedAchievement
x Map CategorizedAchievement Attainment
attainedMap

  renderFlavorTextWidget :: FlavorText -> Widget Name
  renderFlavorTextWidget :: FlavorText -> Widget Name
renderFlavorTextWidget (Freeform Document Syntax
t) = Document Syntax -> Widget Name
drawMarkdown Document Syntax
t
  renderFlavorTextWidget (FTQuotation (Quotation Text
author Text
quoteContent)) =
    forall n. [Widget n] -> Widget n
vBox
      [ forall n. Text -> Widget n
txtWrap Text
quoteContent
      , forall n. Padding -> Widget n -> Widget n
padLeft Padding
Max
          forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Padding -> Widget n -> Widget n
padRight (Int -> Padding
Pad Int
2)
          forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. WrapSettings -> Text -> Widget n
txtWrapWith (WrapSettings
defaultWrapSettings {fillStrategy :: FillStrategy
fillStrategy = Int -> FillStrategy
FillIndent Int
2})
          forall a b. (a -> b) -> a -> b
$ Text
"--" forall a. Semigroup a => a -> a -> a
<> Text
author
      ]

  innerContent :: Widget Name
innerContent =
    forall n. [Widget n] -> Widget n
vBox
      [ forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall n. Widget n
emptyWidget (Int -> Widget Name -> Widget Name
padAllEvenly Int
2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. FlavorText -> Widget Name
renderFlavorTextWidget) forall a b. (a -> b) -> a -> b
$ AchievementInfo -> Maybe FlavorText
humorousElaboration AchievementInfo
details
      , if Bool
wasAttained Bool -> Bool -> Bool
|| Bool -> Bool
not (AchievementInfo -> Bool
isObfuscated AchievementInfo
details)
          then Document Syntax -> Widget Name
drawMarkdown forall a b. (a -> b) -> a -> b
$ AchievementInfo -> Document Syntax
attainmentProcess AchievementInfo
details
          else forall n. Text -> Widget n
txt Text
"???"
      , case forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup CategorizedAchievement
x Map CategorizedAchievement Attainment
attainedMap of
          Maybe Attainment
Nothing -> forall n. Widget n
emptyWidget
          Just Attainment
attainment ->
            forall n. Padding -> Widget n -> Widget n
padTop (Int -> Padding
Pad Int
1) forall a b. (a -> b) -> a -> b
$
              forall n. [Widget n] -> Widget n
vBox
                [ forall n. [Widget n] -> Widget n
hBox
                    [ forall n. Text -> Widget n
txt Text
"Obtained: "
                    , forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
cyanAttr
                        forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. String -> Widget n
str
                        forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%l:%M%P on %b %e, %Y"
                        forall a b. (a -> b) -> a -> b
$ Attainment
attainment forall s a. s -> Getting a s a -> a
^. Lens' Attainment ZonedTime
obtainedAt
                    ]
                , forall a b c. (a -> b -> c) -> b -> a -> c
flip (forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall n. Widget n
emptyWidget) (Attainment
attainment forall s a. s -> Getting a s a -> a
^. Lens' Attainment (Maybe String)
maybeScenarioPath) forall a b. (a -> b) -> a -> b
$ \String
s ->
                    forall n. [Widget n] -> Widget n
hBox
                      [ forall n. Text -> Widget n
txt Text
"Scenario: "
                      , forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
cyanAttr forall a b. (a -> b) -> a -> b
$
                          forall n. String -> Widget n
str String
s
                      ]
                ]
      , forall n. Padding -> Widget n -> Widget n
padTop (Int -> Padding
Pad Int
1) forall a b. (a -> b) -> a -> b
$
          forall n. [Widget n] -> Widget n
hBox
            [ forall n. Text -> Widget n
txt Text
"Effort: "
            , forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
boldAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. String -> Widget n
str forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show forall a b. (a -> b) -> a -> b
$ AchievementInfo -> ExpectedEffort
effort AchievementInfo
details
            ]
      ]

  titleWidget :: Widget n
titleWidget = forall n. Int -> Widget n -> Widget n
padLeftRight Int
1 forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ AchievementInfo -> Text
title AchievementInfo
details
  details :: AchievementInfo
details = CategorizedAchievement -> AchievementInfo
describe CategorizedAchievement
x