module Emanote.View.TaskIndex (renderTasks) where

import Data.IxSet.Typed qualified as Ix
import Data.List.NonEmpty qualified as NE
import Data.Map.Strict qualified as Map
import Data.Map.Syntax ((##))
import Emanote.Model (Model)
import Emanote.Model.Task (Task)
import Emanote.Model.Task qualified as Task
import Emanote.Model.Type qualified as M
import Emanote.Route qualified as R
import Emanote.Route.SiteRoute qualified as SR
import Emanote.View.Common qualified as Common
import Heist.Extra.Splices.List qualified as Splices
import Heist.Extra.Splices.Pandoc qualified as Splices
import Heist.Extra.Splices.Pandoc.Ctx (emptyRenderCtx)
import Heist.Interpreted qualified as HI
import Optics.Operators ((^.))
import Relude
import Text.Pandoc.Definition qualified as B

newtype TaskIndex = TaskIndex {TaskIndex -> Map LMLRoute (NonEmpty Task)
unTaskIndex :: Map R.LMLRoute (NonEmpty Task)}

mkTaskIndex :: Model -> TaskIndex
mkTaskIndex :: Model -> TaskIndex
mkTaskIndex Model
model =
  Map LMLRoute (NonEmpty Task) -> TaskIndex
TaskIndex forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b k. (a -> b) -> Map k a -> Map k b
Map.map forall a. Ord a => NonEmpty a -> NonEmpty a
NE.sort forall a b. (a -> b) -> a -> b
$
    forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith forall a. Semigroup a => a -> a -> a
(<>) forall a b. (a -> b) -> a -> b
$
      forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Task -> Bool
Task._taskChecked) (forall (ixs :: [Type]) a. IxSet ixs a -> [a]
Ix.toList forall a b. (a -> b) -> a -> b
$ Model
model forall k s (is :: [Type]) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (encF :: Type -> Type).
Lens' (ModelT encF) (IxSet TaskIxs Task)
M.modelTasks) forall (f :: Type -> Type) a b. Functor f => f a -> (a -> b) -> f b
<&> \Task
task ->
        (Task
task forall k s (is :: [Type]) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Lens' Task LMLRoute
Task.taskRoute, forall x. One x => OneItem x -> x
one Task
task)

renderTasks :: Model -> LByteString
renderTasks :: Model -> LByteString
renderTasks Model
model = do
  let (LMLRoute
defR, Value
meta) = Model -> (LMLRoute, Value)
Common.defaultRouteMeta Model
model
      tCtx :: TemplateRenderCtx @(Type -> Type) Identity
tCtx = Model
-> LMLRoute -> Value -> TemplateRenderCtx @(Type -> Type) Identity
Common.mkTemplateRenderCtx Model
model LMLRoute
defR Value
meta
      taskIndex :: TaskIndex
taskIndex = Model -> TaskIndex
mkTaskIndex Model
model
      taskGroupSplice :: LMLRoute -> NonEmpty Task -> MapSyntaxM Text (Splice Identity) ()
taskGroupSplice LMLRoute
r NonEmpty Task
tasks = do
        Text
"t:note:url" forall k v. k -> v -> MapSyntax k v
## forall (m :: Type -> Type) (n :: Type -> Type).
Monad m =>
Text -> HeistT n m Template
HI.textSplice (HasCallStack => Model -> SiteRoute -> Text
SR.siteRouteUrl Model
model forall a b. (a -> b) -> a -> b
$ LMLRoute -> SiteRoute
SR.lmlSiteRoute LMLRoute
r)
        Text
"t:note:title" forall k v. k -> v -> MapSyntax k v
## forall {k} (n :: k).
TemplateRenderCtx @k n -> Title -> Splice Identity
Common.titleSplice TemplateRenderCtx @(Type -> Type) Identity
tCtx (forall (f :: Type -> Type). LMLRoute -> ModelT f -> Title
M.modelLookupTitle LMLRoute
r Model
model)
        Text
"t:note:breadcrumbs" forall k v. k -> v -> MapSyntax k v
##
          forall {k} (n :: k).
TemplateRenderCtx @k n -> Model -> LMLRoute -> Splice Identity
Common.routeBreadcrumbs TemplateRenderCtx @(Type -> Type) Identity
tCtx Model
model LMLRoute
r
        Text
"t:tasks" forall k v. k -> v -> MapSyntax k v
## forall a.
[a]
-> Text
-> (a -> MapSyntaxM Text (Splice Identity) ())
-> Splice Identity
Splices.listSplice (forall (t :: Type -> Type) a. Foldable t => t a -> [a]
toList NonEmpty Task
tasks) Text
"task" Task -> MapSyntaxM Text (Splice Identity) ()
taskSplice
      taskSplice :: Task -> MapSyntaxM Text (Splice Identity) ()
taskSplice Task
task = do
        let r :: LMLRoute
r = Task
task forall k s (is :: [Type]) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Lens' Task LMLRoute
Task.taskRoute
        -- TODO: reuse note splice
        Text
"task:description" forall k v. k -> v -> MapSyntax k v
## forall {k} (n :: k).
TemplateRenderCtx @k n
-> (RenderCtx -> Splice Identity) -> Splice Identity
Common.withInlineCtx TemplateRenderCtx @(Type -> Type) Identity
tCtx forall a b. (a -> b) -> a -> b
$ \RenderCtx
ctx ->
          RenderCtx -> Pandoc -> Splice Identity
Splices.pandocSplice RenderCtx
ctx forall a b. (a -> b) -> a -> b
$ Meta -> [Block] -> Pandoc
B.Pandoc forall a. Monoid a => a
mempty forall a b. (a -> b) -> a -> b
$ forall x. One x => OneItem x -> x
one forall a b. (a -> b) -> a -> b
$ [Inline] -> Block
B.Plain forall a b. (a -> b) -> a -> b
$ Task
task forall k s (is :: [Type]) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Lens' Task [Inline]
Task.taskDescription
        Text
"note:title" forall k v. k -> v -> MapSyntax k v
## forall {k} (n :: k).
TemplateRenderCtx @k n -> Title -> Splice Identity
Common.titleSplice TemplateRenderCtx @(Type -> Type) Identity
tCtx (forall (f :: Type -> Type). LMLRoute -> ModelT f -> Title
M.modelLookupTitle LMLRoute
r Model
model)
        Text
"note:url" forall k v. k -> v -> MapSyntax k v
## forall (m :: Type -> Type) (n :: Type -> Type).
Monad m =>
Text -> HeistT n m Template
HI.textSplice (HasCallStack => Model -> SiteRoute -> Text
SR.siteRouteUrl Model
model forall a b. (a -> b) -> a -> b
$ LMLRoute -> SiteRoute
SR.lmlSiteRoute LMLRoute
r)

  Model
-> TemplateName
-> MapSyntaxM Text (Splice Identity) ()
-> LByteString
Common.renderModelTemplate Model
model TemplateName
"templates/special/tasks" forall a b. (a -> b) -> a -> b
$ do
    HasCallStack =>
((RenderCtx -> Splice Identity) -> Splice Identity)
-> Model -> Value -> Title -> MapSyntaxM Text (Splice Identity) ()
Common.commonSplices (forall a b. (a -> b) -> a -> b
$ RenderCtx
emptyRenderCtx) Model
model Value
meta Title
"Task Index"
    let groups :: [(LMLRoute, NonEmpty Task)]
groups =
          forall k a. Map k a -> [(k, a)]
Map.toList (TaskIndex -> Map LMLRoute (NonEmpty Task)
unTaskIndex TaskIndex
taskIndex)
            forall a b. a -> (a -> b) -> b
& forall b a. Ord b => (a -> b) -> [a] -> [a]
sortWith forall a b. (a, b) -> a
fst
    Text
"ema:taskGroups" forall k v. k -> v -> MapSyntax k v
## forall a.
[a]
-> Text
-> (a -> MapSyntaxM Text (Splice Identity) ())
-> Splice Identity
Splices.listSplice [(LMLRoute, NonEmpty Task)]
groups Text
"taskGroup" (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry LMLRoute -> NonEmpty Task -> MapSyntaxM Text (Splice Identity) ()
taskGroupSplice)