{-# LANGUAGE QuasiQuotes #-}
-- | Case study variants.
--
-- Each case study is expected to generate files in a specific pattern that the
-- main `code/Makefile` expects for (a) testing and (b) website deployment.
module Drasil.Generator.CaseStudyVariants
  ( caseStudyMainSRS,
    caseStudyMainSRSWCode,
    caseStudyMainSRSWCodeZoo,
  )
where

import Control.Lens ((^.))
import Data.Char (toLower)

import Drasil.FileHandling (FileLayout, OverwritePolicy(..), directory, localPath, ps,
  writeFiles)
import Drasil.SRS (SRSDecl, mkDoc, SmithEtAlSRS, programName)
import Language.Drasil.Code (Choices)
import qualified Language.Drasil.Sentence.Combinators as S

import Drasil.Generator.Code (genCode, genCodeZoo)
import Drasil.Generator.SRS (genSmithEtAlSrs)
import Drasil.Generator.SRS.TypeCheck (typeCheckSI)
import Drasil.Generator.WriteSystem (setSystemLocale)

-- | Internal: The `build/` subfolder the Makefile expects each case study will
-- build in (other than the website).
caseStudyBuildFolder :: SmithEtAlSRS -> String
caseStudyBuildFolder :: SmithEtAlSRS -> [Char]
caseStudyBuildFolder = (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower ([Char] -> [Char])
-> (SmithEtAlSRS -> [Char]) -> SmithEtAlSRS -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SmithEtAlSRS -> Getting [Char] SmithEtAlSRS [Char] -> [Char]
forall s a. s -> Getting a s a -> a
^. Getting [Char] SmithEtAlSRS [Char]
forall c. HasSmithEtAlSRS c => Lens' c [Char]
Lens' SmithEtAlSRS [Char]
programName)

-- | Internal: Generate documents and construct the SRS directory layout
-- structure (and debug data) for an example.
writeSmithEtAlSrs :: SmithEtAlSRS -> SRSDecl -> String -> IO ([FileLayout], SmithEtAlSRS, String)
writeSmithEtAlSrs :: SmithEtAlSRS
-> SRSDecl -> [Char] -> IO ([FileLayout], SmithEtAlSRS, [Char])
writeSmithEtAlSrs SmithEtAlSRS
syst SRSDecl
srsDecl [Char]
srsFileName = do
  let exampleName :: [Char]
exampleName = SmithEtAlSRS -> [Char]
caseStudyBuildFolder SmithEtAlSRS
syst
      (Document
srs, SmithEtAlSRS
syst') = SmithEtAlSRS
-> SRSDecl -> (CI -> CI -> Sentence) -> (Document, SmithEtAlSRS)
mkDoc SmithEtAlSRS
syst SRSDecl
srsDecl CI -> CI -> Sentence
forall c d. (NamedIdea c, NamedIdea d) => c -> d -> Sentence
S.forT
  SmithEtAlSRS -> IO ()
typeCheckSI SmithEtAlSRS
syst' -- FIXME: This should be done on `System` creation *or* chunk creation!
  let layout :: [FileLayout]
layout = SmithEtAlSRS -> Document -> [Char] -> [FileLayout]
genSmithEtAlSrs SmithEtAlSRS
syst' Document
srs [Char]
srsFileName
  ([FileLayout], SmithEtAlSRS, [Char])
-> IO ([FileLayout], SmithEtAlSRS, [Char])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([FileLayout]
layout, SmithEtAlSRS
syst', [Char]
exampleName)

-- | A case study that only outputs an SRS in each of our supported variants.
caseStudyMainSRS :: SmithEtAlSRS -> SRSDecl -> String -> IO ()
caseStudyMainSRS :: SmithEtAlSRS -> SRSDecl -> [Char] -> IO ()
caseStudyMainSRS SmithEtAlSRS
syst SRSDecl
srsDecl [Char]
srsFileName = do
  IO ()
setSystemLocale
  ([FileLayout]
docLayouts, SmithEtAlSRS
_, [Char]
exampleName) <- SmithEtAlSRS
-> SRSDecl -> [Char] -> IO ([FileLayout], SmithEtAlSRS, [Char])
writeSmithEtAlSrs SmithEtAlSRS
syst SRSDecl
srsDecl [Char]
srsFileName
  OverwritePolicy -> OsPath -> FileLayout -> IO ()
writeFiles OverwritePolicy
OverwriteAllowed OsPath
localPath (FileLayout -> IO ()) -> FileLayout -> IO ()
forall a b. (a -> b) -> a -> b
$ PathSegment -> [FileLayout] -> FileLayout
forall (f :: * -> *).
Foldable f =>
PathSegment -> f FileLayout -> FileLayout
directory [ps|{exampleName}|] [FileLayout]
docLayouts

-- | A case study that outputs both an SRS in each of our supported variants as
-- well as a single chosen software artifact in optionally many programming
-- languages.
caseStudyMainSRSWCode :: SmithEtAlSRS -> SRSDecl -> String -> Choices -> IO ()
caseStudyMainSRSWCode :: SmithEtAlSRS -> SRSDecl -> [Char] -> Choices -> IO ()
caseStudyMainSRSWCode SmithEtAlSRS
syst SRSDecl
srsDecl [Char]
srsFileName Choices
choices = do
  IO ()
setSystemLocale
  ([FileLayout]
docLayouts, SmithEtAlSRS
syst', [Char]
exampleName) <- SmithEtAlSRS
-> SRSDecl -> [Char] -> IO ([FileLayout], SmithEtAlSRS, [Char])
writeSmithEtAlSrs SmithEtAlSRS
syst SRSDecl
srsDecl [Char]
srsFileName
  FileLayout
srcLayout <- SmithEtAlSRS -> Choices -> IO FileLayout
genCode SmithEtAlSRS
syst' Choices
choices
  OverwritePolicy -> OsPath -> FileLayout -> IO ()
writeFiles OverwritePolicy
OverwriteAllowed OsPath
localPath (FileLayout -> IO ()) -> FileLayout -> IO ()
forall a b. (a -> b) -> a -> b
$ PathSegment -> [FileLayout] -> FileLayout
forall (f :: * -> *).
Foldable f =>
PathSegment -> f FileLayout -> FileLayout
directory [ps|{exampleName}|] ([FileLayout] -> FileLayout) -> [FileLayout] -> FileLayout
forall a b. (a -> b) -> a -> b
$ FileLayout
srcLayout FileLayout -> [FileLayout] -> [FileLayout]
forall a. a -> [a] -> [a]
: [FileLayout]
docLayouts

-- | The same as 'caseStudyMainSRSWCode', except it also produces a
-- JupyterNotebook-based lesson plan.
caseStudyMainSRSWCodeZoo :: SmithEtAlSRS -> SRSDecl -> String -> [Choices] -> IO ()
caseStudyMainSRSWCodeZoo :: SmithEtAlSRS -> SRSDecl -> [Char] -> [Choices] -> IO ()
caseStudyMainSRSWCodeZoo SmithEtAlSRS
syst SRSDecl
srsDecl [Char]
srsFileName [Choices]
choices = do
  IO ()
setSystemLocale
  ([FileLayout]
docLayouts, SmithEtAlSRS
syst', [Char]
exampleName) <- SmithEtAlSRS
-> SRSDecl -> [Char] -> IO ([FileLayout], SmithEtAlSRS, [Char])
writeSmithEtAlSrs SmithEtAlSRS
syst SRSDecl
srsDecl [Char]
srsFileName
  [FileLayout]
zooLayouts <- SmithEtAlSRS -> [Choices] -> IO [FileLayout]
genCodeZoo SmithEtAlSRS
syst' [Choices]
choices
  let layout :: FileLayout
layout = PathSegment -> [FileLayout] -> FileLayout
forall (f :: * -> *).
Foldable f =>
PathSegment -> f FileLayout -> FileLayout
directory [ps|{exampleName}|] ([FileLayout] -> FileLayout) -> [FileLayout] -> FileLayout
forall a b. (a -> b) -> a -> b
$ [FileLayout]
docLayouts [FileLayout] -> [FileLayout] -> [FileLayout]
forall a. [a] -> [a] -> [a]
++ [FileLayout]
zooLayouts
  OverwritePolicy -> OsPath -> FileLayout -> IO ()
writeFiles OverwritePolicy
OverwriteAllowed OsPath
localPath FileLayout
layout