module Drasil.Database.SearchTools where

import Control.Lens ((^.))

import Database.Drasil
import Language.Drasil
import Theory.Drasil

-- This is only needed for as long as `TypedUIDRef` is underused.
data TermAbbr = TermAbbr { TermAbbr -> NP
longForm :: NP, TermAbbr -> Maybe String
shortForm :: Maybe String }

-- | Search for a chunk that is an instance of 'Idea' and return its "term" and
-- abbreviation, erroring out if it doesn't exist.
termResolve :: (NP -> Maybe String -> c) -> ChunkDB -> UID -> c
termResolve :: forall c. (NP -> Maybe String -> c) -> ChunkDB -> UID -> c
termResolve NP -> Maybe String -> c
f ChunkDB
db UID
trg
  | (Just IdeaDict
c) <- UID -> ChunkDB -> Maybe IdeaDict
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe IdeaDict            = (NP -> Maybe String -> c) -> IdeaDict -> c
forall t c. Idea t => (NP -> Maybe String -> c) -> t -> c
go NP -> Maybe String -> c
f IdeaDict
c
  | (Just DefinedQuantityDict
c) <- UID -> ChunkDB -> Maybe DefinedQuantityDict
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe DefinedQuantityDict = (NP -> Maybe String -> c) -> DefinedQuantityDict -> c
forall t c. Idea t => (NP -> Maybe String -> c) -> t -> c
go NP -> Maybe String -> c
f DefinedQuantityDict
c
  | (Just ConceptChunk
c) <- UID -> ChunkDB -> Maybe ConceptChunk
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe ConceptChunk        = (NP -> Maybe String -> c) -> ConceptChunk -> c
forall t c. Idea t => (NP -> Maybe String -> c) -> t -> c
go NP -> Maybe String -> c
f ConceptChunk
c
  | (Just UnitDefn
c) <- UID -> ChunkDB -> Maybe UnitDefn
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe UnitDefn            = (NP -> Maybe String -> c) -> UnitDefn -> c
forall t c. Idea t => (NP -> Maybe String -> c) -> t -> c
go NP -> Maybe String -> c
f UnitDefn
c
  | (Just DataDefinition
c) <- UID -> ChunkDB -> Maybe DataDefinition
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe DataDefinition      = (NP -> Maybe String -> c) -> DataDefinition -> c
forall t c. Idea t => (NP -> Maybe String -> c) -> t -> c
go NP -> Maybe String -> c
f DataDefinition
c
  | (Just InstanceModel
c) <- UID -> ChunkDB -> Maybe InstanceModel
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe InstanceModel       = (NP -> Maybe String -> c) -> InstanceModel -> c
forall t c. Idea t => (NP -> Maybe String -> c) -> t -> c
go NP -> Maybe String -> c
f InstanceModel
c
  | (Just GenDefn
c) <- UID -> ChunkDB -> Maybe GenDefn
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe GenDefn             = (NP -> Maybe String -> c) -> GenDefn -> c
forall t c. Idea t => (NP -> Maybe String -> c) -> t -> c
go NP -> Maybe String -> c
f GenDefn
c
  | (Just TheoryModel
c) <- UID -> ChunkDB -> Maybe TheoryModel
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe TheoryModel         = (NP -> Maybe String -> c) -> TheoryModel -> c
forall t c. Idea t => (NP -> Maybe String -> c) -> t -> c
go NP -> Maybe String -> c
f TheoryModel
c
  | (Just ConceptInstance
c) <- UID -> ChunkDB -> Maybe ConceptInstance
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe ConceptInstance     = (NP -> Maybe String -> c) -> ConceptInstance -> c
forall t c. Idea t => (NP -> Maybe String -> c) -> t -> c
go NP -> Maybe String -> c
f ConceptInstance
c
  | Bool
otherwise = String -> c
forall a. HasCallStack => String -> a
error (String -> c) -> String -> c
forall a b. (a -> b) -> a -> b
$ String
"Term: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ UID -> String
forall a. Show a => a -> String
show UID
trg String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" not found in TermMap"
  where
    go :: Idea t => (NP -> Maybe String -> c) -> t -> c
    go :: forall t c. Idea t => (NP -> Maybe String -> c) -> t -> c
go NP -> Maybe String -> c
f' t
c = NP -> Maybe String -> c
f' (t
c t -> Getting NP t NP -> NP
forall s a. s -> Getting a s a -> a
^. Getting NP t NP
forall c. NamedIdea c => Lens' c NP
Lens' t NP
term) (t -> Maybe String
forall c. Idea c => c -> Maybe String
getA t
c)

-- | Find a chunk's "term" and abbreviation, erroring out if it doesn't exist.
termResolve' :: ChunkDB -> UID -> TermAbbr
termResolve' :: ChunkDB -> UID -> TermAbbr
termResolve' = (NP -> Maybe String -> TermAbbr) -> ChunkDB -> UID -> TermAbbr
forall c. (NP -> Maybe String -> c) -> ChunkDB -> UID -> c
termResolve NP -> Maybe String -> TermAbbr
TermAbbr

data DomDefn = DomDefn { DomDefn -> [UID]
domain :: [UID], DomDefn -> Sentence
definition :: Sentence }

-- | Looks up a 'UID' in all tables with concepts from the 'ChunkDB'. If nothing
-- is found, an error is thrown.
defResolve :: ([UID] -> Sentence -> c) -> ChunkDB -> UID -> c
defResolve :: forall c. ([UID] -> Sentence -> c) -> ChunkDB -> UID -> c
defResolve [UID] -> Sentence -> c
f ChunkDB
db UID
trg
  | (Just DefinedQuantityDict
c) <- UID -> ChunkDB -> Maybe DefinedQuantityDict
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe DefinedQuantityDict = ([UID] -> Sentence -> c) -> DefinedQuantityDict -> c
forall c r. Concept c => ([UID] -> Sentence -> r) -> c -> r
go [UID] -> Sentence -> c
f DefinedQuantityDict
c
  | (Just ConceptChunk
c) <- UID -> ChunkDB -> Maybe ConceptChunk
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe ConceptChunk        = ([UID] -> Sentence -> c) -> ConceptChunk -> c
forall c r. Concept c => ([UID] -> Sentence -> r) -> c -> r
go [UID] -> Sentence -> c
f ConceptChunk
c
  | (Just UnitDefn
c) <- UID -> ChunkDB -> Maybe UnitDefn
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe UnitDefn            = ([UID] -> Sentence -> c) -> UnitDefn -> c
forall c r. Concept c => ([UID] -> Sentence -> r) -> c -> r
go [UID] -> Sentence -> c
f UnitDefn
c
  | (Just InstanceModel
c) <- UID -> ChunkDB -> Maybe InstanceModel
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe InstanceModel       = ([UID] -> Sentence -> c) -> InstanceModel -> c
forall c r. Concept c => ([UID] -> Sentence -> r) -> c -> r
go [UID] -> Sentence -> c
f InstanceModel
c
  | (Just GenDefn
c) <- UID -> ChunkDB -> Maybe GenDefn
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe GenDefn             = ([UID] -> Sentence -> c) -> GenDefn -> c
forall c r. Concept c => ([UID] -> Sentence -> r) -> c -> r
go [UID] -> Sentence -> c
f GenDefn
c
  | (Just TheoryModel
c) <- UID -> ChunkDB -> Maybe TheoryModel
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe TheoryModel         = ([UID] -> Sentence -> c) -> TheoryModel -> c
forall c r. Concept c => ([UID] -> Sentence -> r) -> c -> r
go [UID] -> Sentence -> c
f TheoryModel
c
  | (Just ConceptInstance
c) <- UID -> ChunkDB -> Maybe ConceptInstance
forall a. Typeable a => UID -> ChunkDB -> Maybe a
find UID
trg ChunkDB
db :: Maybe ConceptInstance     = ([UID] -> Sentence -> c) -> ConceptInstance -> c
forall c r. Concept c => ([UID] -> Sentence -> r) -> c -> r
go [UID] -> Sentence -> c
f ConceptInstance
c
  | Bool
otherwise = String -> c
forall a. HasCallStack => String -> a
error (String -> c) -> String -> c
forall a b. (a -> b) -> a -> b
$ String
"Definition: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ UID -> String
forall a. Show a => a -> String
show UID
trg String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" not found in ConceptMap"
  where
    go :: Concept c => ([UID] -> Sentence -> r) -> c -> r
    go :: forall c r. Concept c => ([UID] -> Sentence -> r) -> c -> r
go [UID] -> Sentence -> r
f' c
c = [UID] -> Sentence -> r
f' (c -> [UID]
forall c. ConceptDomain c => c -> [UID]
cdom 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
defn)

defResolve' :: ChunkDB -> UID -> DomDefn
defResolve' :: ChunkDB -> UID -> DomDefn
defResolve' = ([UID] -> Sentence -> DomDefn) -> ChunkDB -> UID -> DomDefn
forall c. ([UID] -> Sentence -> c) -> ChunkDB -> UID -> c
defResolve [UID] -> Sentence -> DomDefn
DomDefn

findAllDataDefns :: ChunkDB -> [DataDefinition]
findAllDataDefns :: ChunkDB -> [DataDefinition]
findAllDataDefns = ChunkDB -> [DataDefinition]
forall a. IsChunk a => ChunkDB -> [a]
findAll

findAllGenDefns :: ChunkDB -> [GenDefn]
findAllGenDefns :: ChunkDB -> [GenDefn]
findAllGenDefns = ChunkDB -> [GenDefn]
forall a. IsChunk a => ChunkDB -> [a]
findAll

findAllInstMods :: ChunkDB -> [InstanceModel]
findAllInstMods :: ChunkDB -> [InstanceModel]
findAllInstMods = ChunkDB -> [InstanceModel]
forall a. IsChunk a => ChunkDB -> [a]
findAll

findAllTheoryMods :: ChunkDB -> [TheoryModel]
findAllTheoryMods :: ChunkDB -> [TheoryModel]
findAllTheoryMods = ChunkDB -> [TheoryModel]
forall a. IsChunk a => ChunkDB -> [a]
findAll

findAllConcInsts :: ChunkDB -> [ConceptInstance]
findAllConcInsts :: ChunkDB -> [ConceptInstance]
findAllConcInsts = ChunkDB -> [ConceptInstance]
forall a. IsChunk a => ChunkDB -> [a]
findAll

findAllIdeaDicts :: ChunkDB -> [IdeaDict]
findAllIdeaDicts :: ChunkDB -> [IdeaDict]
findAllIdeaDicts = ChunkDB -> [IdeaDict]
forall a. IsChunk a => ChunkDB -> [a]
findAll

findAllDefinedQuantities :: ChunkDB -> [DefinedQuantityDict]
findAllDefinedQuantities :: ChunkDB -> [DefinedQuantityDict]
findAllDefinedQuantities = ChunkDB -> [DefinedQuantityDict]
forall a. IsChunk a => ChunkDB -> [a]
findAll

findAllCitations :: ChunkDB -> [Citation]
findAllCitations :: ChunkDB -> [Citation]
findAllCitations = ChunkDB -> [Citation]
forall a. IsChunk a => ChunkDB -> [a]
findAll

findAllLabelledContent :: ChunkDB -> [LabelledContent]
findAllLabelledContent :: ChunkDB -> [LabelledContent]
findAllLabelledContent = ChunkDB -> [LabelledContent]
forall a. IsChunk a => ChunkDB -> [a]
findAll