-- | Contains functions for generating code comments that describe a chunk.
module Language.Drasil.Code.Imperative.Comments (
  getComment, getCommentBrief
) where

import Control.Monad.State (get)
import Control.Lens ((^.))
import Text.PrettyPrint.HughesPJ (Doc, (<+>), colon, empty, parens, render)

import Drasil.Code.CodeVar (CodeIdea(..))
import Drasil.Database (HasUID(..))
import Drasil.Database.SearchTools (DomDefn (definition), defResolve')
import Language.Drasil
import Language.Drasil.Code.Imperative.DrasilState (GenState, DrasilState(..))
import Language.Drasil.Printers (oneLineSentenceDoc, oneLineUnitDoc)
import Drasil.System (systemdb)

-- | Gets a plain renderering of the term for a chunk.
getTermDoc :: (CodeIdea c) => c -> GenState Doc
getTermDoc :: forall c. CodeIdea c => c -> GenState Doc
getTermDoc c
c = do
  g <- StateT DrasilState Identity DrasilState
forall s (m :: * -> *). MonadState s m => m s
get
  return $ oneLineSentenceDoc (printfo g) $ phrase $ codeChunk c

-- | Gets a plain rendering of the definition of a chunk, preceded by a colon
-- as it is intended to follow the term for the chunk. Returns empty if the
-- chunk has no definition.
getDefnDoc :: (CodeIdea c) => c -> GenState Doc
getDefnDoc :: forall c. CodeIdea c => c -> GenState Doc
getDefnDoc c
c = do
  g <- StateT DrasilState Identity DrasilState
forall s (m :: * -> *). MonadState s m => m s
get
  let db = DrasilState
g DrasilState -> Getting ChunkDB DrasilState ChunkDB -> ChunkDB
forall s a. s -> Getting a s a -> a
^. Getting ChunkDB DrasilState ChunkDB
forall c. HasSystemMeta c => Lens' c ChunkDB
Lens' DrasilState ChunkDB
systemdb
  return $ ((<+>) colon . oneLineSentenceDoc (printfo g))
    (definition $ defResolve' db (codeChunk c ^. uid))

-- | Gets a plain rendering of the unit of a chunk in parentheses,
-- or empty if it has no unit.
getUnitsDoc :: (CodeIdea c) => c -> Doc
getUnitsDoc :: forall c. CodeIdea c => c -> Doc
getUnitsDoc c
c = Doc -> (UnitDefn -> Doc) -> Maybe UnitDefn -> Doc
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Doc
empty (Doc -> Doc
parens (Doc -> Doc) -> (UnitDefn -> Doc) -> UnitDefn -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. USymb -> Doc
oneLineUnitDoc (USymb -> Doc) -> (UnitDefn -> USymb) -> UnitDefn -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitDefn -> USymb
forall u. HasUnitSymbol u => u -> USymb
usymb)
  (CodeChunk -> Maybe UnitDefn
forall u. MayHaveUnit u => u -> Maybe UnitDefn
getUnit (CodeChunk -> Maybe UnitDefn) -> CodeChunk -> Maybe UnitDefn
forall a b. (a -> b) -> a -> b
$ c -> CodeChunk
forall c. CodeIdea c => c -> CodeChunk
codeChunk c
c)

-- | Generates a comment string for a chunk, including the term,
-- definition (if applicable), and unit (if applicable).
getComment :: (CodeIdea c) => c -> GenState String
getComment :: forall c. CodeIdea c => c -> GenState String
getComment c
l = do
  t <- c -> GenState Doc
forall c. CodeIdea c => c -> GenState Doc
getTermDoc c
l
  d <- getDefnDoc l
  let u = c -> Doc
forall c. CodeIdea c => c -> Doc
getUnitsDoc c
l
  return $ render $ (t <> d) <+> u

getCommentBrief :: (CodeIdea c) => c -> GenState String
getCommentBrief :: forall c. CodeIdea c => c -> GenState String
getCommentBrief c
l = do
  t <- c -> GenState Doc
forall c. CodeIdea c => c -> GenState Doc
getTermDoc c
l
  let u = c -> Doc
forall c. CodeIdea c => c -> Doc
getUnitsDoc c
l
  return $ render $ t <+> u