module Emanote.Pandoc.Renderer.Query (
  queryResolvingSplice,
  noteSpliceMap,
) where

import Data.List qualified as List
import Data.Map.Syntax ((##))
import Data.Text qualified as T
import Emanote.Model (Model)
import Emanote.Model.Note qualified as MN
import Emanote.Model.Query qualified as Q
import Emanote.Model.Title qualified as Tit
import Emanote.Pandoc.BuiltinFilters (preparePandoc)
import Emanote.Pandoc.Renderer (PandocBlockRenderer)
import Emanote.Route (LMLRoute)
import Emanote.Route.SiteRoute qualified as SR
import Heist qualified as H
import Heist.Extra qualified as HE
import Heist.Extra.Splices.Pandoc (RenderCtx)
import Heist.Interpreted qualified as HI
import Heist.Splices.Json qualified as HJ
import Optics.Operators ((^.))
import Relude
import Text.Pandoc.Definition qualified as B

queryResolvingSplice :: PandocBlockRenderer Model LMLRoute
queryResolvingSplice :: PandocBlockRenderer Model LMLRoute
queryResolvingSplice Model
model PandocRenderers Model LMLRoute
_nr RenderCtx
ctx LMLRoute
noteRoute Block
blk = do
  B.CodeBlock
    (Text
_id', [Text]
classes, [(Text, Text)]
_attrs)
    (Text -> Maybe Query
Q.parseQuery -> Just Query
q) <-
    forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Block
blk
  forall (f :: Type -> Type). Alternative f => Bool -> f ()
guard forall a b. (a -> b) -> a -> b
$ forall (t :: Type -> Type) a.
(Foldable t, Eq a) =>
a -> t a -> Bool
List.elem Text
"query" [Text]
classes
  let mOtherCls :: Maybe Text
mOtherCls = forall a. [a] -> Maybe (NonEmpty a)
nonEmpty (forall a. Eq a => a -> [a] -> [a]
List.delete Text
"query" [Text]
classes) forall (f :: Type -> Type) a b. Functor f => f a -> (a -> b) -> f b
<&> Text -> [Text] -> Text
T.intercalate Text
" " forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: Type -> Type) a. Foldable t => t a -> [a]
toList
      queryTpl :: ByteString
queryTpl = forall a b. ConvertUtf8 a b => a -> b
encodeUtf8 forall a b. (a -> b) -> a -> b
$ Text
"/templates/filters/query-" forall a. Semigroup a => a -> a -> a
<> forall a. a -> Maybe a -> a
fromMaybe Text
"default" Maybe Text
mOtherCls
  forall (f :: Type -> Type) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ do
    Template
tpl <- forall (m :: Type -> Type) (n :: Type -> Type).
Monad n =>
ByteString -> HeistT m n Template
HE.lookupHtmlTemplateMust ByteString
queryTpl
    Template -> Splices (Splice Identity) -> Splice Identity
HE.runCustomTemplate Template
tpl forall a b. (a -> b) -> a -> b
$ do
      Text
"query" forall k v. k -> v -> MapSyntax k v
##
        forall (m :: Type -> Type) (n :: Type -> Type).
Monad m =>
Text -> HeistT n m Template
HI.textSplice (forall b a. (Show a, IsString b) => a -> b
show Query
q)
      Text
"result" forall k v. k -> v -> MapSyntax k v
##
        (forall (n :: Type -> Type).
Monad n =>
Splices (Splice n) -> Splice n
HI.runChildrenWith forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((RenderCtx -> Splice Identity) -> Splice Identity)
-> Model -> Note -> Splices (Splice Identity)
noteSpliceMap (forall a b. (a -> b) -> a -> b
$ RenderCtx
ctx) Model
model) forall b (m :: Type -> Type) (f :: Type -> Type) a.
(Monoid b, Monad m, Foldable f) =>
(a -> m b) -> f a -> m b
`foldMapM` LMLRoute -> Model -> Query -> [Note]
Q.runQuery LMLRoute
noteRoute Model
model Query
q

-- TODO: Reuse this elsewhere
noteSpliceMap ::
  ((RenderCtx -> HI.Splice Identity) -> HI.Splice Identity) ->
  Model ->
  MN.Note ->
  H.Splices (HI.Splice Identity)
noteSpliceMap :: ((RenderCtx -> Splice Identity) -> Splice Identity)
-> Model -> Note -> Splices (Splice Identity)
noteSpliceMap (RenderCtx -> Splice Identity) -> Splice Identity
withCtx Model
model Note
note = do
  Text
"ema:note:title" forall k v. k -> v -> MapSyntax k v
## (RenderCtx -> Splice Identity) -> Splice Identity
withCtx forall a b. (a -> b) -> a -> b
$ \RenderCtx
ctx -> forall b.
(Walkable Inline b, (b :: Type) ~ ([Inline] :: Type)) =>
RenderCtx -> (b -> b) -> Title -> Splice Identity
Tit.titleSplice RenderCtx
ctx forall b. Walkable Inline b => b -> b
preparePandoc (Note -> Title
MN._noteTitle Note
note)
  Text
"ema: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 forall a b. (a -> b) -> a -> b
$ Note
note forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Lens' Note LMLRoute
MN.noteRoute)
  Text
"ema:note:metadata" forall k v. k -> v -> MapSyntax k v
## forall a (n :: Type -> Type). (ToJSON a, Monad n) => a -> Splice n
HJ.bindJson (Note
note forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Lens' Note Value
MN.noteMeta)