{-# LANGUAGE TemplateHaskell #-}

-- | Defines a package extension for GOOL, with functions for pairing a GOOL
-- program with auxiliary, non-source-code files.
module Language.Drasil.Code.Imperative.GOOL.ClassInterface (
  -- DataTypes
  SoftwareDossierState, makeSds, headers, sources, mainMod,
  -- Typeclasses
  AuxiliarySym(..),
  -- Functions
  package, sampleInput, auxFromData
) where

import Text.PrettyPrint.HughesPJ (Doc)

import Drasil.GOOL (ProgData, onCodeList)
import Language.Drasil.Printers (PrintingInformation)

import Language.Drasil (Expr)
import Language.Drasil.Code.DataDesc (DataDesc)
import Language.Drasil.Code.FileData (FileAndContents(..), PackageData,
  fileAndContents, packageData)
import Language.Drasil.Code.FileNames (sampleInputName)
import Language.Drasil.Choices (Comments, ImplementationType, Verbosity)
import Language.Drasil.Code.Imperative.WriteInput (makeInputFile)
import Language.Drasil.Code.Imperative.README (ReadMeInfo(..))

import Control.Lens (makeLenses)

data SoftwareDossierState = Sds {
  SoftwareDossierState -> [FilePath]
_headers :: [FilePath], -- Used by Drasil for doxygen config gen
  SoftwareDossierState -> [FilePath]
_sources :: [FilePath], -- Used by Drasil for doxygen config and Makefile gen
  SoftwareDossierState -> Maybe FilePath
_mainMod :: Maybe FilePath -- Used by Drasil generator to access main
                             -- mod file path (needed in Makefile generation)
}
makeLenses ''SoftwareDossierState

makeSds :: [FilePath] -> [FilePath] -> Maybe FilePath -> SoftwareDossierState
makeSds :: [FilePath] -> [FilePath] -> Maybe FilePath -> SoftwareDossierState
makeSds [FilePath]
headerFiles [FilePath]
sourceFiles Maybe FilePath
mainModule = Sds {
    _headers :: [FilePath]
_headers = [FilePath]
headerFiles,
    _sources :: [FilePath]
_sources = [FilePath]
sourceFiles,
    _mainMod :: Maybe FilePath
_mainMod = Maybe FilePath
mainModule
  }

-- | Members of this class must have a doxygen configuration, ReadMe file,
-- omptimize doxygen document, information necessary for a makefile, and
-- auxiliary helper documents
class AuxiliarySym r where
  doxConfig :: String -> SoftwareDossierState -> Verbosity -> r FileAndContents
  readMe ::  ReadMeInfo -> r FileAndContents

  optimizeDox :: r Doc

  makefile :: [FilePath] -> ImplementationType -> [Comments] -> SoftwareDossierState ->
    ProgData -> r FileAndContents

  auxHelperDoc :: r Doc -> Doc

package :: (Monad r) => ProgData -> [r FileAndContents] -> r (PackageData ProgData)
package :: forall (r :: * -> *).
Monad r =>
ProgData -> [r FileAndContents] -> r (PackageData ProgData)
package ProgData
p = ([FileAndContents] -> PackageData ProgData)
-> [r FileAndContents] -> r (PackageData ProgData)
forall (m :: * -> *) a b. Monad m => ([a] -> b) -> [m a] -> m b
onCodeList (ProgData -> [FileAndContents] -> PackageData ProgData
forall a. a -> [FileAndContents] -> PackageData a
packageData ProgData
p)

sampleInput :: (Applicative r) => PrintingInformation -> DataDesc -> [Expr] ->
  r FileAndContents
sampleInput :: forall (r :: * -> *).
Applicative r =>
PrintingInformation -> DataDesc -> [Expr] -> r FileAndContents
sampleInput PrintingInformation
db DataDesc
d [Expr]
sd = FilePath -> Doc -> r FileAndContents
forall (r :: * -> *).
Applicative r =>
FilePath -> Doc -> r FileAndContents
auxFromData FilePath
sampleInputName (PrintingInformation -> DataDesc -> [Expr] -> Doc
makeInputFile PrintingInformation
db DataDesc
d [Expr]
sd)

auxFromData :: Applicative r => FilePath -> Doc -> r FileAndContents
auxFromData :: forall (r :: * -> *).
Applicative r =>
FilePath -> Doc -> r FileAndContents
auxFromData FilePath
fp Doc
d = FileAndContents -> r FileAndContents
forall a. a -> r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FileAndContents -> r FileAndContents)
-> FileAndContents -> r FileAndContents
forall a b. (a -> b) -> a -> b
$ FilePath -> Doc -> FileAndContents
fileAndContents FilePath
fp Doc
d