{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards   #-}
module Patat.Eval.Internal
    ( EvalBlocks
    , EvalBlock (..)
    , renderEvalBlock
    ) where


--------------------------------------------------------------------------------
import qualified Control.Concurrent.Async    as Async
import           Data.CaseInsensitive        (CI)
import qualified Data.HashMap.Strict         as HMS
import qualified Data.Text                   as T
import           Patat.Presentation.Settings
import           Patat.Presentation.Syntax


--------------------------------------------------------------------------------
type EvalBlocks = HMS.HashMap Var EvalBlock


--------------------------------------------------------------------------------
-- | Block that needs to be evaluated.
data EvalBlock = EvalBlock
    { EvalBlock -> EvalSettings
ebSettings :: !EvalSettings
    , EvalBlock -> [CI Text]
ebClasses  :: ![CI T.Text]
    , EvalBlock -> Text
ebInput    :: !T.Text
    , EvalBlock -> Maybe (Async ())
ebAsync    :: !(Maybe (Async.Async ()))
    }


--------------------------------------------------------------------------------
renderEvalBlock :: EvalBlock -> T.Text -> [Block]
renderEvalBlock :: EvalBlock -> Text -> [Block]
renderEvalBlock EvalBlock {[CI Text]
Maybe (Async ())
Text
EvalSettings
ebSettings :: EvalBlock -> EvalSettings
ebClasses :: EvalBlock -> [CI Text]
ebInput :: EvalBlock -> Text
ebAsync :: EvalBlock -> Maybe (Async ())
ebSettings :: EvalSettings
ebClasses :: [CI Text]
ebInput :: Text
ebAsync :: Maybe (Async ())
..} Text
out = case EvalSettings -> EvalSettingsContainer
evalContainer EvalSettings
ebSettings of
    EvalSettingsContainer
EvalContainerCode   -> [[CI Text] -> Text -> Block
CodeBlock [CI Text]
classes Text
out]
    EvalSettingsContainer
EvalContainerNone   -> [Format -> Text -> Block
RawBlock Format
fmt Text
out]
    EvalSettingsContainer
EvalContainerInline -> [[Inline] -> Block
Plain [Format -> Text -> Inline
RawInline Format
fmt Text
out]]
  where
    fmt :: Format
fmt = Format
"eval"

    -- The classes for the new code block are copied from the old one if
    -- unspecified, or the syntax specified in the eval settings.
    classes :: [CI Text]
classes = [CI Text] -> (CI Text -> [CI Text]) -> Maybe (CI Text) -> [CI Text]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [CI Text]
ebClasses CI Text -> [CI Text]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (CI Text) -> [CI Text]) -> Maybe (CI Text) -> [CI Text]
forall a b. (a -> b) -> a -> b
$ EvalSettings -> Maybe (CI Text)
evalSyntax EvalSettings
ebSettings