-- | Contains functions to create the concept related chunk types found in
-- "Language.Drasil.Chunk.Concept.Core".
module Language.Drasil.Chunk.Concept (
  -- * Concept Chunks
  -- ** From an idea ('IdeaDict')
  ConceptChunk, cncpt, cncpt', cncpt'', cncpt''', cw,
  -- ** From a 'ConceptChunk'
  ConceptInstance, cic
  ) where

import Control.Lens ((^.))

import Drasil.Database (HasUID(uid), nsUid, UID, mkUid)

import Language.Drasil.Classes (ConceptDomain(cdom), Concept)
import Language.Drasil.Chunk.Concept.Core (ConceptChunk(ConDict), ConceptInstance(ConInst))
import Language.Drasil.Sentence (Sentence(S))
import Language.Drasil.Chunk.NamedIdea (NamedIdea (..), Idea (..))
import Language.Drasil.NaturalLanguage.English.NounPhrase (NP, pn)
import Language.Drasil.ShortName (shortname')
import qualified Language.Drasil.Classes as D (defn)

-- FIXME: There should only be two smart constructors ultimately for
-- `ConceptChunk`s. One with an abbreviation, the other without. In other words,
-- only `cncpt` and `cncpt'` should exist. The other ones should not. The
-- problem here is that dealing with the other ones requires domain analysis.

-- | Construct a 'ConceptChunk'.
cncpt :: Concept dom =>
  -- | The 'UID'.
  UID ->
  -- The 'term' being defined.
  NP ->
  -- | The definition of the 'term'
  Sentence ->
  -- | The term's abbreviation.
  String ->
  -- | The domain the 'term' belongs to.
  [dom] -> ConceptChunk
cncpt :: forall dom.
Concept dom =>
UID -> NP -> Sentence -> String -> [dom] -> ConceptChunk
cncpt UID
u NP
trm Sentence
defn String
accAbbr = UID -> NP -> Maybe String -> Sentence -> [UID] -> ConceptChunk
ConDict UID
u NP
trm (String -> Maybe String
forall a. a -> Maybe a
Just String
accAbbr) Sentence
defn ([UID] -> ConceptChunk)
-> ([dom] -> [UID]) -> [dom] -> ConceptChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (dom -> UID) -> [dom] -> [UID]
forall a b. (a -> b) -> [a] -> [b]
map (dom -> Getting UID dom UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID dom UID
forall c. HasUID c => Getter c UID
Getter dom UID
uid)

-- | Construct a 'ConceptChunk'.
cncpt' :: Concept dom =>
  -- | The 'UID'.
  UID ->
  -- | The 'term' being defined.
  NP ->
  -- | The definition of the 'term'
  Sentence ->
  -- | The domain the 'term' belongs to.
  [dom] -> ConceptChunk
cncpt' :: forall dom.
Concept dom =>
UID -> NP -> Sentence -> [dom] -> ConceptChunk
cncpt' UID
u NP
trm Sentence
defn = UID -> NP -> Maybe String -> Sentence -> [UID] -> ConceptChunk
ConDict UID
u NP
trm Maybe String
forall a. Maybe a
Nothing Sentence
defn ([UID] -> ConceptChunk)
-> ([dom] -> [UID]) -> [dom] -> ConceptChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (dom -> UID) -> [dom] -> [UID]
forall a b. (a -> b) -> [a] -> [b]
map (dom -> Getting UID dom UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID dom UID
forall c. HasUID c => Getter c UID
Getter dom UID
uid)

-- | Construct a 'ConceptChunk'.
cncpt'' ::
  -- | The 'UID'.
  UID ->
  -- | The 'term' being defined.
  NP ->
  -- | The definition of the 'term'
  Sentence ->
  -- | The term's abbreviation.
  String -> ConceptChunk
cncpt'' :: UID -> NP -> Sentence -> String -> ConceptChunk
cncpt'' UID
u NP
trm Sentence
defn String
accAbbr = UID -> NP -> Sentence -> String -> [ConceptChunk] -> ConceptChunk
forall dom.
Concept dom =>
UID -> NP -> Sentence -> String -> [dom] -> ConceptChunk
cncpt UID
u NP
trm Sentence
defn String
accAbbr ([] :: [ConceptChunk])

-- | Construct a 'ConceptChunk'.
cncpt''' ::
  -- | The 'UID'.
  UID ->
  -- | The 'term' being defined.
  NP ->
  -- | The definition of the 'term'
  Sentence -> ConceptChunk
cncpt''' :: UID -> NP -> Sentence -> ConceptChunk
cncpt''' UID
u NP
trm Sentence
defn = UID -> NP -> Maybe String -> Sentence -> [UID] -> ConceptChunk
ConDict UID
u NP
trm Maybe String
forall a. Maybe a
Nothing Sentence
defn []

{-# DEPRECATED cw
  "Chunk down-casting is strongly discouraged. If you want to construct a `ConceptChunk`, use one of its normal constructors." #-}

-- | For projecting out to the 'ConceptChunk' data-type.
cw :: Concept c => c -> ConceptChunk
cw :: forall c. Concept c => c -> ConceptChunk
cw c
c = UID -> NP -> Maybe String -> Sentence -> [UID] -> ConceptChunk
ConDict (c
c c -> Getting UID c UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID c UID
forall c. HasUID c => Getter c UID
Getter c UID
uid) (c
c c -> Getting NP c NP -> NP
forall s a. s -> Getting a s a -> a
^. Getting NP c NP
forall c. NamedIdea c => Lens' c NP
Lens' c NP
term) (c -> Maybe String
forall c. Idea c => c -> Maybe String
getA c
c) (c
c 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
Lens' c Sentence
D.defn) (c -> [UID]
forall c. ConceptDomain c => c -> [UID]
cdom c
c)

-- | Constructor for a 'ConceptInstance'. Takes in the Reference Address
-- ('String'), a definition ('Sentence'), a short name ('String'), and a domain
-- (for explicit tagging).
cic :: Concept c => String -> Sentence -> String -> c -> ConceptInstance
cic :: forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic String
u Sentence
d String
sn c
dom = UID -> ConceptChunk -> String -> ShortName -> ConceptInstance
ConInst (String -> UID -> UID
nsUid String
"instance" (UID -> UID) -> UID -> UID
forall a b. (a -> b) -> a -> b
$ ConceptChunk
icc ConceptChunk -> Getting UID ConceptChunk UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID ConceptChunk UID
forall c. HasUID c => Getter c UID
Getter ConceptChunk UID
uid) ConceptChunk
icc String
u (ShortName -> ConceptInstance) -> ShortName -> ConceptInstance
forall a b. (a -> b) -> a -> b
$ Sentence -> ShortName
shortname' (String -> Sentence
S String
sn)
  where
    icc :: ConceptChunk
icc = UID -> NP -> Sentence -> [c] -> ConceptChunk
forall {a}.
HasUID a =>
UID -> NP -> Sentence -> [a] -> ConceptChunk
cc (String -> UID
mkUid String
u) (String -> NP
pn String
sn) Sentence
d [c
dom]
    cc :: UID -> NP -> Sentence -> [a] -> ConceptChunk
cc UID
u' NP
n Sentence
d' [a]
l = UID -> NP -> Maybe String -> Sentence -> [UID] -> ConceptChunk
ConDict UID
u' NP
n Maybe String
forall a. Maybe a
Nothing Sentence
d' ([UID] -> ConceptChunk) -> [UID] -> ConceptChunk
forall a b. (a -> b) -> a -> b
$ (a -> UID) -> [a] -> [UID]
forall a b. (a -> b) -> [a] -> [b]
map (a -> Getting UID a UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID a UID
forall c. HasUID c => Getter c UID
Getter a UID
uid) [a]
l