-- | General functions that are useful in manipulating some Drasil types into
-- printable 'Contents'.
module Drasil.Document.Contents (
  -- * List Creation Functions
  enumBullet, enumBulletU, enumSimple,
  enumSimpleU, mkEnumSimpleD,

  -- * Displaying Expressions
  lbldExpr, unlbldExpr, unlbldCode,

  -- * Folds
  foldlSP, foldlSP_, foldlSPCol
) where

import Control.Lens ((^.))

import Language.Drasil
  ( Definition(..), HasShortName(..), getSentSN, mkRawLC, ulcc, mkParagraph, foldlSent_
  , foldlSent, foldlSentCol
  , LabelledContent, RawContent(Enumeration, EqnBlock, CodeBlock), Contents(UlC), ListTuple
  , ItemType(Flat), ListType(Simple), Expr, Referable(refAdd), ModelExpr, Reference, Sentence (..))
import Drasil.Sentence.Combinators (bulletFlat, mkEnumAbbrevList)

-- | Displays a given expression and attaches a 'Reference' to it.
lbldExpr :: ModelExpr -> Reference -> LabelledContent
lbldExpr :: ModelExpr -> Reference -> LabelledContent
lbldExpr ModelExpr
c = RawContent -> Reference -> LabelledContent
mkRawLC (ModelExpr -> RawContent
EqnBlock ModelExpr
c)

-- | Same as 'eqUnR' except content is unlabelled (does not attach a 'Reference').
unlbldExpr :: ModelExpr -> Contents
unlbldExpr :: ModelExpr -> Contents
unlbldExpr ModelExpr
c = UnlabelledContent -> Contents
UlC (UnlabelledContent -> Contents) -> UnlabelledContent -> Contents
forall a b. (a -> b) -> a -> b
$ RawContent -> UnlabelledContent
ulcc (RawContent -> UnlabelledContent)
-> RawContent -> UnlabelledContent
forall a b. (a -> b) -> a -> b
$ ModelExpr -> RawContent
EqnBlock ModelExpr
c

-- | Unlabelled code expression
unlbldCode :: Expr -> Contents
unlbldCode :: Expr -> Contents
unlbldCode Expr
c = UnlabelledContent -> Contents
UlC (UnlabelledContent -> Contents) -> UnlabelledContent -> Contents
forall a b. (a -> b) -> a -> b
$ RawContent -> UnlabelledContent
ulcc (RawContent -> UnlabelledContent)
-> RawContent -> UnlabelledContent
forall a b. (a -> b) -> a -> b
$ Expr -> RawContent
CodeBlock Expr
c

-- | Creates a bulleted list.
enumBullet :: Reference -> [Sentence] -> LabelledContent --FIXME: should Enumeration be labelled?
enumBullet :: Reference -> [Sentence] -> LabelledContent
enumBullet Reference
lb [Sentence]
s = RawContent -> Reference -> LabelledContent
mkRawLC (ListType -> RawContent
Enumeration (ListType -> RawContent) -> ListType -> RawContent
forall a b. (a -> b) -> a -> b
$ [Sentence] -> ListType
bulletFlat [Sentence]
s) Reference
lb

-- | Same as 'enumBullet' but unlabelled.
enumBulletU :: [Sentence] -> Contents --FIXME: should Enumeration be labelled?
enumBulletU :: [Sentence] -> Contents
enumBulletU [Sentence]
s =  UnlabelledContent -> Contents
UlC (UnlabelledContent -> Contents) -> UnlabelledContent -> Contents
forall a b. (a -> b) -> a -> b
$ RawContent -> UnlabelledContent
ulcc (RawContent -> UnlabelledContent)
-> RawContent -> UnlabelledContent
forall a b. (a -> b) -> a -> b
$ ListType -> RawContent
Enumeration (ListType -> RawContent) -> ListType -> RawContent
forall a b. (a -> b) -> a -> b
$ [Sentence] -> ListType
bulletFlat [Sentence]
s

-- | Currently Unused. Creates a simple bulleted list that labels things with
-- a title and number:
--
--     * lb - Reference,
--     * s - start index for the enumeration,
--     * t - title of the list,
--     * l - list to be enumerated.
--
-- For example, if we want to create a list of data definitions, we could call the function as follows:
--
-- > enumSimple _ 2 (S "DD") [def1, def2, ...]
--
-- And the resulting 'LabelledContent' would be rendered as:
--
--     * DD2: def1
--     * DD3: def2
--     * DD4: def3 ...
enumSimple :: Reference -> Integer -> Sentence -> [Sentence] -> LabelledContent --FIXME: should Enumeration be labelled?
enumSimple :: Reference -> Integer -> Sentence -> [Sentence] -> LabelledContent
enumSimple Reference
lb Integer
s Sentence
t [Sentence]
l = RawContent -> Reference -> LabelledContent
mkRawLC (ListType -> RawContent
Enumeration (ListType -> RawContent) -> ListType -> RawContent
forall a b. (a -> b) -> a -> b
$ [ListTuple] -> ListType
Simple ([ListTuple] -> ListType) -> [ListTuple] -> ListType
forall a b. (a -> b) -> a -> b
$ [(Sentence, ItemType)] -> [ListTuple]
noRefsLT ([(Sentence, ItemType)] -> [ListTuple])
-> [(Sentence, ItemType)] -> [ListTuple]
forall a b. (a -> b) -> a -> b
$ Integer -> Sentence -> [Sentence] -> [(Sentence, ItemType)]
mkEnumAbbrevList Integer
s Sentence
t [Sentence]
l) Reference
lb

-- | Same as 'enumSimple' but unlabelled.
enumSimpleU :: Integer -> Sentence -> [Sentence] -> Contents --FIXME: should Enumeration be labelled?
enumSimpleU :: Integer -> Sentence -> [Sentence] -> Contents
enumSimpleU Integer
s Sentence
t [Sentence]
l = UnlabelledContent -> Contents
UlC (UnlabelledContent -> Contents) -> UnlabelledContent -> Contents
forall a b. (a -> b) -> a -> b
$ RawContent -> UnlabelledContent
ulcc (RawContent -> UnlabelledContent)
-> RawContent -> UnlabelledContent
forall a b. (a -> b) -> a -> b
$ ListType -> RawContent
Enumeration (ListType -> RawContent) -> ListType -> RawContent
forall a b. (a -> b) -> a -> b
$ [ListTuple] -> ListType
Simple ([ListTuple] -> ListType) -> [ListTuple] -> ListType
forall a b. (a -> b) -> a -> b
$ [(Sentence, ItemType)] -> [ListTuple]
noRefsLT ([(Sentence, ItemType)] -> [ListTuple])
-> [(Sentence, ItemType)] -> [ListTuple]
forall a b. (a -> b) -> a -> b
$ Integer -> Sentence -> [Sentence] -> [(Sentence, ItemType)]
mkEnumAbbrevList Integer
s Sentence
t [Sentence]
l

-- | Converts lists of tuples containing a title ('Sentence') and 'ItemType' into
-- a bulleted list (['ListTuple']) which can be used with 'Contents' but not directly referable.
noRefsLT :: [(Sentence, ItemType)] -> [ListTuple]
noRefsLT :: [(Sentence, ItemType)] -> [ListTuple]
noRefsLT [(Sentence, ItemType)]
a = ([Sentence] -> [ItemType] -> [Maybe String] -> [ListTuple])
-> ([Sentence], [ItemType]) -> [Maybe String] -> [ListTuple]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry [Sentence] -> [ItemType] -> [Maybe String] -> [ListTuple]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 ([(Sentence, ItemType)] -> ([Sentence], [ItemType])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Sentence, ItemType)]
a) ([Maybe String] -> [ListTuple]) -> [Maybe String] -> [ListTuple]
forall a b. (a -> b) -> a -> b
$ Maybe String -> [Maybe String]
forall a. a -> [a]
repeat Maybe String
forall a. Maybe a
Nothing

-- | Convenience function for transforming referable concepts into a bulleted list.
-- Used in drasil-docLang in making the assumptions, goals, and requirements sections.
-- Output is of the kind @Concept Name: definition of concept@.
mkEnumSimpleD :: (Referable c, HasShortName c, Definition c) => [c] -> [Contents]
mkEnumSimpleD :: forall c.
(Referable c, HasShortName c, Definition c) =>
[c] -> [Contents]
mkEnumSimpleD = (c -> ListTuple) -> [c] -> [Contents]
forall a. (a -> ListTuple) -> [a] -> [Contents]
mkEnumSimple ((c -> ListTuple) -> [c] -> [Contents])
-> (c -> ListTuple) -> [c] -> [Contents]
forall a b. (a -> b) -> a -> b
$ (c -> ItemType) -> c -> ListTuple
forall c.
(Referable c, HasShortName c) =>
(c -> ItemType) -> c -> ListTuple
mkListTuple (\c
x -> Sentence -> ItemType
Flat (Sentence -> ItemType) -> Sentence -> ItemType
forall a b. (a -> b) -> a -> b
$ c
x c -> Getting Sentence c Sentence -> Sentence
forall s a. s -> Getting a s a -> a
^. Getting Sentence c Sentence
forall c. Definition c => Lens' c Sentence
Lens' c Sentence
defn)

-- | Helper function for converting a list of something into a bulleted list.
-- Used in 'mkEnumSimpleD'.
mkEnumSimple :: (a -> ListTuple) -> [a] -> [Contents]
mkEnumSimple :: forall a. (a -> ListTuple) -> [a] -> [Contents]
mkEnumSimple a -> ListTuple
_ [] = []
mkEnumSimple a -> ListTuple
f [a]
xs = [UnlabelledContent -> Contents
UlC (UnlabelledContent -> Contents) -> UnlabelledContent -> Contents
forall a b. (a -> b) -> a -> b
$ RawContent -> UnlabelledContent
ulcc (RawContent -> UnlabelledContent)
-> RawContent -> UnlabelledContent
forall a b. (a -> b) -> a -> b
$ ListType -> RawContent
Enumeration (ListType -> RawContent) -> ListType -> RawContent
forall a b. (a -> b) -> a -> b
$ [ListTuple] -> ListType
Simple ([ListTuple] -> ListType) -> [ListTuple] -> ListType
forall a b. (a -> b) -> a -> b
$ (a -> ListTuple) -> [a] -> [ListTuple]
forall a b. (a -> b) -> [a] -> [b]
map a -> ListTuple
f [a]
xs]

-- | Helper function that creates a bullet point from a function and an item.
-- Used in 'mkEnumSimpleD'.
mkListTuple :: (Referable c, HasShortName c) => (c -> ItemType) -> c -> ListTuple
mkListTuple :: forall c.
(Referable c, HasShortName c) =>
(c -> ItemType) -> c -> ListTuple
mkListTuple c -> ItemType
f c
x = (ShortName -> Sentence
getSentSN (ShortName -> Sentence) -> ShortName -> Sentence
forall a b. (a -> b) -> a -> b
$ c -> ShortName
forall s. HasShortName s => s -> ShortName
shortname c
x, c -> ItemType
f c
x, String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ c -> String
forall s. Referable s => s -> String
refAdd c
x)

-- | Fold sentences then turns into content using 'foldlSent'.
foldlSP :: [Sentence] -> Contents
foldlSP :: [Sentence] -> Contents
foldlSP = Sentence -> Contents
mkParagraph (Sentence -> Contents)
-> ([Sentence] -> Sentence) -> [Sentence] -> Contents
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Sentence] -> Sentence
foldlSent

-- | Same as 'foldlSP' but uses 'foldlSent_'.
foldlSP_ :: [Sentence] -> Contents
foldlSP_ :: [Sentence] -> Contents
foldlSP_ = Sentence -> Contents
mkParagraph (Sentence -> Contents)
-> ([Sentence] -> Sentence) -> [Sentence] -> Contents
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Sentence] -> Sentence
foldlSent_

-- | Same as 'foldlSP' but uses 'foldlSentCol'.
foldlSPCol :: [Sentence] -> Contents
foldlSPCol :: [Sentence] -> Contents
foldlSPCol = Sentence -> Contents
mkParagraph (Sentence -> Contents)
-> ([Sentence] -> Sentence) -> [Sentence] -> Contents
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Sentence] -> Sentence
foldlSentCol