module Drasil.ExtractCommon (
  sentToExp, extractMExprs,
  extractSents, extractSents',
  extractChRefs
) where

import Control.Lens((^.))
import qualified Data.Set as S

import Drasil.Database (UID)
import Language.Drasil hiding (getCitations, Manual, Verb)
import Language.Drasil.Development (lnames)

-- | Extracts all referenced 'UID's from things that have 'RawContent's.
extractChRefs :: HasContents a => [a] -> S.Set UID
extractChRefs :: forall a. HasContents a => [a] -> Set UID
extractChRefs = [Set UID] -> Set UID
forall (f :: * -> *) a. (Foldable f, Ord a) => f (Set a) -> Set a
S.unions ([Set UID] -> Set UID) -> ([a] -> [Set UID]) -> [a] -> Set UID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Sentence -> Set UID) -> [Sentence] -> [Set UID]
forall a b. (a -> b) -> [a] -> [b]
map Sentence -> Set UID
lnames ([Sentence] -> [Set UID])
-> ([a] -> [Sentence]) -> [a] -> [Set UID]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [Sentence]
forall a. HasContents a => [a] -> [Sentence]
extractSents'

-- | Extracts all 'ModelExpr's mentioned in a 'Sentence'.
sentToExp :: Sentence -> [ModelExpr]
sentToExp :: Sentence -> [ModelExpr]
sentToExp ((:+:) Sentence
s1 Sentence
s2) = Sentence -> [ModelExpr]
sentToExp Sentence
s1 [ModelExpr] -> [ModelExpr] -> [ModelExpr]
forall a. [a] -> [a] -> [a]
++ Sentence -> [ModelExpr]
sentToExp Sentence
s2
sentToExp (E ModelExpr
e) = [ModelExpr
e]
sentToExp Ch{} = []
sentToExp SyCh{} = []
sentToExp Sy{} = []
sentToExp NP{} = []
sentToExp S{} = []
sentToExp P{} = []
sentToExp (Ref UID
_ Sentence
s RefInfo
_) = Sentence -> [ModelExpr]
sentToExp Sentence
s
sentToExp (Quote Sentence
s) = Sentence -> [ModelExpr]
sentToExp Sentence
s
sentToExp Sentence
Percent = []
sentToExp Sentence
EmptyS = []

-- | Extracts 'ModelExpr's from something that 'HasContents'.
extractMExprs :: HasContents a => a -> [ModelExpr]
extractMExprs :: forall a. HasContents a => a -> [ModelExpr]
extractMExprs = (Sentence -> [ModelExpr]) -> [Sentence] -> [ModelExpr]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Sentence -> [ModelExpr]
sentToExp ([Sentence] -> [ModelExpr])
-> (a -> [Sentence]) -> a -> [ModelExpr]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [Sentence]
forall a. HasContents a => a -> [Sentence]
extractSents

-- | Extracts 'Sentence's from something that 'HasContents'.
extractSents :: HasContents a => a -> [Sentence]
extractSents :: forall a. HasContents a => a -> [Sentence]
extractSents = RawContent -> [Sentence]
go (RawContent -> [Sentence]) -> (a -> RawContent) -> a -> [Sentence]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Getting RawContent a RawContent -> RawContent
forall s a. s -> Getting a s a -> a
^. Getting RawContent a RawContent
forall c. HasContents c => Lens' c RawContent
Lens' a RawContent
accessContents)
  where
    -- | Extracts 'Sentence's from 'RawContent'.
    go :: RawContent -> [Sentence]
    go :: RawContent -> [Sentence]
go (Table [Sentence]
s1 [[Sentence]]
s2 Sentence
t Bool
_)   = Sentence
t Sentence -> [Sentence] -> [Sentence]
forall a. a -> [a] -> [a]
: [Sentence]
s1 [Sentence] -> [Sentence] -> [Sentence]
forall a. [a] -> [a] -> [a]
++ [[Sentence]] -> [Sentence]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Sentence]]
s2
    go (Paragraph Sentence
s)       = [Sentence
s]
    go (EqnBlock ModelExpr
e)        = [ModelExpr -> Sentence
eS ModelExpr
e]
    go (CodeBlock Expr
e)       = [Expr -> Sentence
forall t. Express t => t -> Sentence
eS' Expr
e]
    go (DerivBlock Sentence
h [RawContent]
d)    = Sentence
h Sentence -> [Sentence] -> [Sentence]
forall a. a -> [a] -> [a]
: (RawContent -> [Sentence]) -> [RawContent] -> [Sentence]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap RawContent -> [Sentence]
go [RawContent]
d
    go (Enumeration ListType
lst)   = ListType -> [Sentence]
goList ListType
lst
    go (Figure Sentence
l Filepath
_ MaxWidthPercent
_ HasCaption
_)    = [Sentence
l]
    go (Bib BibRef
_)             = []
    go (Graph [(Sentence, Sentence)]
sss Maybe MaxWidthPercent
_ Maybe MaxWidthPercent
_ Sentence
l)   = let ([Sentence]
ls, [Sentence]
rs) = [(Sentence, Sentence)] -> ([Sentence], [Sentence])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Sentence, Sentence)]
sss
                              in Sentence
l Sentence -> [Sentence] -> [Sentence]
forall a. a -> [a] -> [a]
: [Sentence]
ls [Sentence] -> [Sentence] -> [Sentence]
forall a. [a] -> [a] -> [a]
++ [Sentence]
rs
    go (Defini DType
_ [(Filepath, [Contents])]
ics)      = ((Filepath, [Contents]) -> [Sentence])
-> [(Filepath, [Contents])] -> [Sentence]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((Contents -> [Sentence]) -> [Contents] -> [Sentence]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Contents -> [Sentence]
forall a. HasContents a => a -> [Sentence]
extractSents ([Contents] -> [Sentence])
-> ((Filepath, [Contents]) -> [Contents])
-> (Filepath, [Contents])
-> [Sentence]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Filepath, [Contents]) -> [Contents]
forall a b. (a, b) -> b
snd) [(Filepath, [Contents])]
ics

    -- | Extracts 'Sentence's from lists.
    goList :: ListType -> [Sentence]
    goList :: ListType -> [Sentence]
goList (Bullet [(ItemType, Maybe Filepath)]
it)      = ((ItemType, Maybe Filepath) -> [Sentence])
-> [(ItemType, Maybe Filepath)] -> [Sentence]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ItemType -> [Sentence]
goItems (ItemType -> [Sentence])
-> ((ItemType, Maybe Filepath) -> ItemType)
-> (ItemType, Maybe Filepath)
-> [Sentence]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ItemType, Maybe Filepath) -> ItemType
forall a b. (a, b) -> a
fst) [(ItemType, Maybe Filepath)]
it
    goList (Numeric [(ItemType, Maybe Filepath)]
it)     = ((ItemType, Maybe Filepath) -> [Sentence])
-> [(ItemType, Maybe Filepath)] -> [Sentence]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ItemType -> [Sentence]
goItems (ItemType -> [Sentence])
-> ((ItemType, Maybe Filepath) -> ItemType)
-> (ItemType, Maybe Filepath)
-> [Sentence]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ItemType, Maybe Filepath) -> ItemType
forall a b. (a, b) -> a
fst) [(ItemType, Maybe Filepath)]
it
    goList (Simple [ListTuple]
lp)      = (ListTuple -> [Sentence]) -> [ListTuple] -> [Sentence]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ListTuple -> [Sentence]
goListTitle [ListTuple]
lp
    goList (Desc [ListTuple]
lp)        = (ListTuple -> [Sentence]) -> [ListTuple] -> [Sentence]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ListTuple -> [Sentence]
goListTitle [ListTuple]
lp
    goList (Definitions [ListTuple]
lp) = (ListTuple -> [Sentence]) -> [ListTuple] -> [Sentence]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ListTuple -> [Sentence]
goListTitle [ListTuple]
lp

    -- | Extracts 'Sentence's from list headers.
    goListTitle :: ListTuple -> [Sentence]
    goListTitle :: ListTuple -> [Sentence]
goListTitle (Sentence
t, ItemType
it, Maybe Filepath
_) = Sentence
t Sentence -> [Sentence] -> [Sentence]
forall a. a -> [a] -> [a]
: ItemType -> [Sentence]
goItems ItemType
it

    -- | Extract 'Sentence's from 'ItemType's and their nested 'ListType's.
    goItems :: ItemType -> [Sentence]
    goItems :: ItemType -> [Sentence]
goItems (Flat Sentence
s) = [Sentence
s]
    goItems (Nested Sentence
h ListType
lt) = Sentence
h Sentence -> [Sentence] -> [Sentence]
forall a. a -> [a] -> [a]
: ListType -> [Sentence]
goList ListType
lt

-- | Extracts 'Sentence's from a list of 'Contents'.
extractSents' :: HasContents a => [a] -> [Sentence]
extractSents' :: forall a. HasContents a => [a] -> [Sentence]
extractSents' = (a -> [Sentence]) -> [a] -> [Sentence]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap a -> [Sentence]
forall a. HasContents a => a -> [Sentence]
extractSents