-- | Utilities to get grab certain chunks (from 'Expr', 'Sentence', etc) by
-- 'UID' and dereference the chunk it refers to.
module Drasil.GetChunks (ccss, ccss', combine, vars, citeDB) where

import Language.Drasil
import Language.Drasil.Development
import Language.Drasil.ModelExpr.Development (meDep)

import Database.Drasil (ChunkDB, defResolve', symbResolve,
  citationTable, DomDefn(definition))

import Drasil.System (System, systemdb)

import Control.Lens ((^.))
import Data.List (nub, sortBy)
import qualified Data.Map as M

-- | Gets a list of quantities ('DefinedQuantityDict') from an equation in order to print.
vars :: ModelExpr -> ChunkDB -> [DefinedQuantityDict]
vars :: ModelExpr -> ChunkDB -> [DefinedQuantityDict]
vars ModelExpr
e ChunkDB
m = (UID -> DefinedQuantityDict) -> [UID] -> [DefinedQuantityDict]
forall a b. (a -> b) -> [a] -> [b]
map (ChunkDB -> UID -> DefinedQuantityDict
symbResolve ChunkDB
m) ([UID] -> [DefinedQuantityDict]) -> [UID] -> [DefinedQuantityDict]
forall a b. (a -> b) -> a -> b
$ ModelExpr -> [UID]
meDep ModelExpr
e

-- | Gets a list of quantities ('DefinedQuantityDict') from a 'Sentence' in order to print.
vars' :: Sentence -> ChunkDB -> [DefinedQuantityDict]
vars' :: Sentence -> ChunkDB -> [DefinedQuantityDict]
vars' Sentence
a ChunkDB
m = (UID -> DefinedQuantityDict) -> [UID] -> [DefinedQuantityDict]
forall a b. (a -> b) -> [a] -> [b]
map (ChunkDB -> UID -> DefinedQuantityDict
symbResolve ChunkDB
m) ([UID] -> [DefinedQuantityDict]) -> [UID] -> [DefinedQuantityDict]
forall a b. (a -> b) -> a -> b
$ Sentence -> [UID]
sdep Sentence
a

-- | Combines the functions of 'vars' and 'concpt' to create a list of 'DefinedQuantityDict's from a 'Sentence'.
combine :: Sentence -> ChunkDB -> [DefinedQuantityDict]
combine :: Sentence -> ChunkDB -> [DefinedQuantityDict]
combine Sentence
a ChunkDB
m = (DefinedQuantityDict -> Sentence -> DefinedQuantityDict)
-> [DefinedQuantityDict] -> [Sentence] -> [DefinedQuantityDict]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith DefinedQuantityDict -> Sentence -> DefinedQuantityDict
forall c.
(Quantity c, MayHaveUnit c) =>
c -> Sentence -> DefinedQuantityDict
dqdQd (Sentence -> ChunkDB -> [DefinedQuantityDict]
vars' Sentence
a ChunkDB
m) (Sentence -> ChunkDB -> [Sentence]
concpt Sentence
a ChunkDB
m)

-- | Combines the functions of 'vars' and 'concpt' to create a list of 'DefinedQuantityDict's from an equation.
combine' :: ModelExpr -> ChunkDB -> [DefinedQuantityDict]
combine' :: ModelExpr -> ChunkDB -> [DefinedQuantityDict]
combine' ModelExpr
a ChunkDB
m = (DefinedQuantityDict -> Sentence -> DefinedQuantityDict)
-> [DefinedQuantityDict] -> [Sentence] -> [DefinedQuantityDict]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith DefinedQuantityDict -> Sentence -> DefinedQuantityDict
forall c.
(Quantity c, MayHaveUnit c) =>
c -> Sentence -> DefinedQuantityDict
dqdQd (ModelExpr -> ChunkDB -> [DefinedQuantityDict]
vars ModelExpr
a ChunkDB
m) (ModelExpr -> ChunkDB -> [Sentence]
concpt' ModelExpr
a ChunkDB
m)

-- | Gets a list of defined quantities ('DefinedQuantityDict's) from 'Sentence's and expressions that are contained in the database ('ChunkDB').
ccss :: [Sentence] -> [ModelExpr] -> ChunkDB -> [DefinedQuantityDict]
ccss :: [Sentence] -> [ModelExpr] -> ChunkDB -> [DefinedQuantityDict]
ccss [Sentence]
s [ModelExpr]
e ChunkDB
c = [DefinedQuantityDict] -> [DefinedQuantityDict]
forall a. Eq a => [a] -> [a]
nub ([DefinedQuantityDict] -> [DefinedQuantityDict])
-> [DefinedQuantityDict] -> [DefinedQuantityDict]
forall a b. (a -> b) -> a -> b
$ (Sentence -> [DefinedQuantityDict])
-> [Sentence] -> [DefinedQuantityDict]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Sentence -> ChunkDB -> [DefinedQuantityDict]
`combine` ChunkDB
c) [Sentence]
s [DefinedQuantityDict]
-> [DefinedQuantityDict] -> [DefinedQuantityDict]
forall a. [a] -> [a] -> [a]
++ (ModelExpr -> [DefinedQuantityDict])
-> [ModelExpr] -> [DefinedQuantityDict]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModelExpr -> ChunkDB -> [DefinedQuantityDict]
`combine'` ChunkDB
c) [ModelExpr]
e

-- | Gets a list of quantities ('DefinedQuantityDict's) from 'Sentence's and expressions that are contained in the database ('ChunkDB').
ccss' :: [Sentence] -> [ModelExpr] -> ChunkDB -> [DefinedQuantityDict]
ccss' :: [Sentence] -> [ModelExpr] -> ChunkDB -> [DefinedQuantityDict]
ccss' [Sentence]
s [ModelExpr]
e ChunkDB
c = [DefinedQuantityDict] -> [DefinedQuantityDict]
forall a. Eq a => [a] -> [a]
nub ([DefinedQuantityDict] -> [DefinedQuantityDict])
-> [DefinedQuantityDict] -> [DefinedQuantityDict]
forall a b. (a -> b) -> a -> b
$ (Sentence -> [DefinedQuantityDict])
-> [Sentence] -> [DefinedQuantityDict]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Sentence -> ChunkDB -> [DefinedQuantityDict]
`vars'` ChunkDB
c) [Sentence]
s [DefinedQuantityDict]
-> [DefinedQuantityDict] -> [DefinedQuantityDict]
forall a. [a] -> [a] -> [a]
++ (ModelExpr -> [DefinedQuantityDict])
-> [ModelExpr] -> [DefinedQuantityDict]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModelExpr -> ChunkDB -> [DefinedQuantityDict]
`vars` ChunkDB
c) [ModelExpr]
e

-- | Gets a list of concepts ('ConceptChunk') from a 'Sentence' in order to print.
concpt :: Sentence -> ChunkDB -> [Sentence]
concpt :: Sentence -> ChunkDB -> [Sentence]
concpt Sentence
a ChunkDB
m = (UID -> Sentence) -> [UID] -> [Sentence]
forall a b. (a -> b) -> [a] -> [b]
map (DomDefn -> Sentence
definition (DomDefn -> Sentence) -> (UID -> DomDefn) -> UID -> Sentence
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ChunkDB -> UID -> DomDefn
defResolve' ChunkDB
m) ([UID] -> [Sentence]) -> [UID] -> [Sentence]
forall a b. (a -> b) -> a -> b
$ Sentence -> [UID]
sdep Sentence
a

-- | Gets a list of concepts ('ConceptChunk') from an expression in order to print.
concpt' :: ModelExpr -> ChunkDB -> [Sentence]
concpt' :: ModelExpr -> ChunkDB -> [Sentence]
concpt' ModelExpr
a ChunkDB
m = (UID -> Sentence) -> [UID] -> [Sentence]
forall a b. (a -> b) -> [a] -> [b]
map (DomDefn -> Sentence
definition (DomDefn -> Sentence) -> (UID -> DomDefn) -> UID -> Sentence
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ChunkDB -> UID -> DomDefn
defResolve' ChunkDB
m) ([UID] -> [Sentence]) -> [UID] -> [Sentence]
forall a b. (a -> b) -> a -> b
$ ModelExpr -> [UID]
meDep ModelExpr
a

-- | Extract bibliography entries for a system.
citeDB :: System -> BibRef
citeDB :: System -> BibRef
citeDB System
si = (Citation -> Citation -> Ordering) -> BibRef -> BibRef
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy Citation -> Citation -> Ordering
forall c. HasFields c => c -> c -> Ordering
compareAuthYearTitle (BibRef -> BibRef) -> BibRef -> BibRef
forall a b. (a -> b) -> a -> b
$ ((Citation, Int) -> Citation) -> [(Citation, Int)] -> BibRef
forall a b. (a -> b) -> [a] -> [b]
map (Citation, Int) -> Citation
forall a b. (a, b) -> a
fst ([(Citation, Int)] -> BibRef) -> [(Citation, Int)] -> BibRef
forall a b. (a -> b) -> a -> b
$ Map UID (Citation, Int) -> [(Citation, Int)]
forall k a. Map k a -> [a]
M.elems (Map UID (Citation, Int) -> [(Citation, Int)])
-> Map UID (Citation, Int) -> [(Citation, Int)]
forall a b. (a -> b) -> a -> b
$ System
si System
-> Getting
     (Map UID (Citation, Int)) System (Map UID (Citation, Int))
-> Map UID (Citation, Int)
forall s a. s -> Getting a s a -> a
^. ((ChunkDB -> Const (Map UID (Citation, Int)) ChunkDB)
-> System -> Const (Map UID (Citation, Int)) System
forall c. HasSystem c => Lens' c ChunkDB
Lens' System ChunkDB
systemdb ((ChunkDB -> Const (Map UID (Citation, Int)) ChunkDB)
 -> System -> Const (Map UID (Citation, Int)) System)
-> ((Map UID (Citation, Int)
     -> Const (Map UID (Citation, Int)) (Map UID (Citation, Int)))
    -> ChunkDB -> Const (Map UID (Citation, Int)) ChunkDB)
-> Getting
     (Map UID (Citation, Int)) System (Map UID (Citation, Int))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map UID (Citation, Int)
 -> Const (Map UID (Citation, Int)) (Map UID (Citation, Int)))
-> ChunkDB -> Const (Map UID (Citation, Int)) ChunkDB
Lens' ChunkDB (Map UID (Citation, Int))
citationTable)