-- | 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 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 forall a b. (a -> b) -> a -> b
$ RawContent -> UnlabelledContent
ulcc 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 forall a b. (a -> b) -> a -> b
$ RawContent -> UnlabelledContent
ulcc 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 forall a b. (a -> b) -> a -> b
$ ListType -> RawContent
Enumeration 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 forall a b. (a -> b) -> a -> b
$ RawContent -> UnlabelledContent
ulcc forall a b. (a -> b) -> a -> b
$ ListType -> RawContent
Enumeration 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 forall a b. (a -> b) -> a -> b
$ ListType -> RawContent
Enumeration forall a b. (a -> b) -> a -> b
$ [ListTuple] -> ListType
Simple forall a b. (a -> b) -> a -> b
$ [(Sentence, ItemType)] -> [ListTuple]
noRefsLT 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 forall a b. (a -> b) -> a -> b
$ RawContent -> UnlabelledContent
ulcc forall a b. (a -> b) -> a -> b
$ ListType -> RawContent
Enumeration forall a b. (a -> b) -> a -> b
$ [ListTuple] -> ListType
Simple forall a b. (a -> b) -> a -> b
$ [(Sentence, ItemType)] -> [ListTuple]
noRefsLT 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 = forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 (forall a b. [(a, b)] -> ([a], [b])
unzip [(Sentence, ItemType)]
a) forall a b. (a -> b) -> a -> b
$ forall a. a -> [a]
repeat 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 = forall a. (a -> ListTuple) -> [a] -> [Contents]
mkEnumSimple forall a b. (a -> b) -> a -> b
$ forall c.
(Referable c, HasShortName c) =>
(c -> ItemType) -> c -> ListTuple
mkListTuple (\c
x -> Sentence -> ItemType
Flat forall a b. (a -> b) -> a -> b
$ c
x forall s a. s -> Getting a s a -> a
^. forall c. Definition c => 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 forall a b. (a -> b) -> a -> b
$ RawContent -> UnlabelledContent
ulcc forall a b. (a -> b) -> a -> b
$ ListType -> RawContent
Enumeration forall a b. (a -> b) -> a -> b
$ [ListTuple] -> ListType
Simple forall a b. (a -> b) -> a -> b
$ 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 forall a b. (a -> b) -> a -> b
$ forall s. HasShortName s => s -> ShortName
shortname c
x, c -> ItemType
f c
x, forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall s. Referable s => s -> String
refAdd c
x)