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

  -- * Displaying Expressions
  lbldExpr, unlbldExpr,
  unlbldCode
) where

import Language.Drasil.Classes (Definition(..))
import Language.Drasil.ShortName (HasShortName(..), getSentSN)
import Language.Drasil.Document (llcc, ulcc)
import Language.Drasil.Document.Core
    (LabelledContent,
     RawContent(Enumeration, EqnBlock, CodeBlock),
     Contents(UlC),
     ListTuple,
     ItemType(Flat),
     ListType(Simple))
import Language.Drasil.ModelExpr.Lang (ModelExpr)
import Language.Drasil.CodeExpr.Lang (CodeExpr)
import Language.Drasil.Reference (Reference)
import Language.Drasil.Sentence (Sentence (..))
import Language.Drasil.Document.Combinators (bulletFlat, mkEnumAbbrevList)
import Language.Drasil.Label.Type ( Referable(refAdd) )

import Control.Lens ((^.))

-- | Displays a given expression and attaches a 'Reference' to it.
lbldExpr :: ModelExpr -> Reference -> LabelledContent
lbldExpr :: ModelExpr -> Reference -> LabelledContent
lbldExpr ModelExpr
c Reference
lbl = Reference -> RawContent -> LabelledContent
llcc Reference
lbl (RawContent -> LabelledContent) -> RawContent -> LabelledContent
forall a b. (a -> b) -> a -> b
$ 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 :: CodeExpr -> Contents
unlbldCode :: CodeExpr -> Contents
unlbldCode CodeExpr
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
$ CodeExpr -> RawContent
CodeBlock CodeExpr
c

-- | Creates a bulleted list.
enumBullet :: Reference -> [Sentence] -> LabelledContent --FIXME: should Enumeration be labelled?
enumBullet :: Reference -> [Sentence] -> LabelledContent
enumBullet Reference
lb [Sentence]
s = Reference -> RawContent -> LabelledContent
llcc Reference
lb (RawContent -> LabelledContent) -> RawContent -> LabelledContent
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

-- | 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 = Reference -> RawContent -> LabelledContent
llcc Reference
lb (RawContent -> LabelledContent) -> RawContent -> LabelledContent
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

-- | 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)