-- | 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
) 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),
      Contents(UlC),
      ListTuple,
      ItemType(Flat),
      ListType(Simple) )
import Language.Drasil.ModelExpr.Lang ( ModelExpr )
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 c :: ModelExpr
c lbl :: 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 c :: 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

-- | Creates a bulleted list.
enumBullet :: Reference -> [Sentence] -> LabelledContent --FIXME: should Enumeration be labelled?
enumBullet :: Reference -> [Sentence] -> LabelledContent
enumBullet lb :: Reference
lb s :: [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 s :: [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 lb :: Reference
lb s :: Integer
s t :: Sentence
t l :: [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 s :: Integer
s t :: Sentence
t l :: [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 a :: [(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 :: [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 (\x :: 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
defn)

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

-- | 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 :: (c -> ItemType) -> c -> ListTuple
mkListTuple f :: c -> ItemType
f x :: 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)