module Drasil.System.Core (
  Purpose, Background, Scope, Motivation,
  SystemMeta,
  HasSystemMeta(..),
  mkSystemMeta,
) where

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

import Drasil.Database (ChunkDB, HasUID(..), HasChunkRefs(..))
import Language.Drasil (Sentence, People)

import Drasil.System.ProjectName (ProjectName, HasProjectName(..))

-- | Project Example purpose.
type Purpose = [Sentence]
-- | Project Example background information, used in the 'What' section of
-- README.
type Background = [Sentence]
-- | Project Example scope.
type Scope = [Sentence]
-- | Project Example motivation.
type Motivation = [Sentence]

data SystemMeta = SystemMeta
  { SystemMeta -> ProjectName
_projName   :: ProjectName
  , SystemMeta -> People
_authors    :: People
  , SystemMeta -> Purpose
_purpose    :: Purpose
  , SystemMeta -> Purpose
_background :: Background
  , SystemMeta -> Purpose
_scope      :: Scope
  , SystemMeta -> Purpose
_motivation :: Motivation
  , SystemMeta -> ChunkDB
_systemdb   :: ChunkDB
  }
makeClassy ''SystemMeta

instance HasUID SystemMeta where
  uid :: Getter SystemMeta UID
uid = (ProjectName -> f ProjectName) -> SystemMeta -> f SystemMeta
forall c. HasSystemMeta c => Lens' c ProjectName
Lens' SystemMeta ProjectName
projName ((ProjectName -> f ProjectName) -> SystemMeta -> f SystemMeta)
-> ((UID -> f UID) -> ProjectName -> f ProjectName)
-> (UID -> f UID)
-> SystemMeta
-> f SystemMeta
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UID -> f UID) -> ProjectName -> f ProjectName
forall c. HasUID c => Getter c UID
Getter ProjectName UID
uid

instance HasProjectName SystemMeta where
  projectName :: Lens' SystemMeta ProjectName
projectName = (ProjectName -> f ProjectName) -> SystemMeta -> f SystemMeta
forall c. HasSystemMeta c => Lens' c ProjectName
Lens' SystemMeta ProjectName
projName

instance HasChunkRefs SystemMeta where
  chunkRefs :: SystemMeta -> Set UID
chunkRefs SystemMeta
x = [Set UID] -> Set UID
forall (f :: * -> *) a. (Foldable f, Ord a) => f (Set a) -> Set a
S.unions [
      ProjectName -> Set UID
forall a. HasChunkRefs a => a -> Set UID
chunkRefs (SystemMeta
x SystemMeta
-> Getting ProjectName SystemMeta ProjectName -> ProjectName
forall s a. s -> Getting a s a -> a
^. Getting ProjectName SystemMeta ProjectName
forall c. HasSystemMeta c => Lens' c ProjectName
Lens' SystemMeta ProjectName
projName),
      People -> Set UID
forall a. HasChunkRefs a => a -> Set UID
chunkRefs (SystemMeta
x SystemMeta -> Getting People SystemMeta People -> People
forall s a. s -> Getting a s a -> a
^. Getting People SystemMeta People
forall c. HasSystemMeta c => Lens' c People
Lens' SystemMeta People
authors),
      Purpose -> Set UID
forall a. HasChunkRefs a => a -> Set UID
chunkRefs (SystemMeta
x SystemMeta -> Getting Purpose SystemMeta Purpose -> Purpose
forall s a. s -> Getting a s a -> a
^. Getting Purpose SystemMeta Purpose
forall c. HasSystemMeta c => Lens' c Purpose
Lens' SystemMeta Purpose
background),
      Purpose -> Set UID
forall a. HasChunkRefs a => a -> Set UID
chunkRefs (SystemMeta
x SystemMeta -> Getting Purpose SystemMeta Purpose -> Purpose
forall s a. s -> Getting a s a -> a
^. Getting Purpose SystemMeta Purpose
forall c. HasSystemMeta c => Lens' c Purpose
Lens' SystemMeta Purpose
scope),
      Purpose -> Set UID
forall a. HasChunkRefs a => a -> Set UID
chunkRefs (SystemMeta
x SystemMeta -> Getting Purpose SystemMeta Purpose -> Purpose
forall s a. s -> Getting a s a -> a
^. Getting Purpose SystemMeta Purpose
forall c. HasSystemMeta c => Lens' c Purpose
Lens' SystemMeta Purpose
motivation)
    ]

mkSystemMeta :: ProjectName -> People -> Purpose -> Background -> Scope ->
  Motivation -> ChunkDB -> SystemMeta
mkSystemMeta :: ProjectName
-> People
-> Purpose
-> Purpose
-> Purpose
-> Purpose
-> ChunkDB
-> SystemMeta
mkSystemMeta = ProjectName
-> People
-> Purpose
-> Purpose
-> Purpose
-> Purpose
-> ChunkDB
-> SystemMeta
SystemMeta