{-# LANGUAGE PostfixOperators #-}
-- | The logic to render Java auxiliary files is contained in this module
module Language.Drasil.Code.Imperative.GOOL.LanguageRenderer.JavaRenderer (
  JavaProject(..)
) where

import Prelude hiding (break,print,sin,cos,tan,floor,(<>))
import Data.List (intercalate)

import Drasil.GOOL (jName, jVersion)

import Language.Drasil.Choices (ImplementationType(..))
import Language.Drasil.Code.Imperative.GOOL.ClassInterface (AuxiliarySym(..))
import Language.Drasil.Code.Imperative.README (ReadMeInfo(..))
import qualified
  Language.Drasil.Code.Imperative.GOOL.LanguageRenderer.LanguagePolymorphic as
  G (doxConfig, readMe, makefile, noRunIfLib, doxDocConfig, docIfEnabled)
import Language.Drasil.Code.Imperative.Build.AST (BuildConfig, BuildName(..),
  Ext(..), Runnable, NameOpts(NameOpts), asFragment, buildSingle,
  buildAllAdditionalName, includeExt, inCodePackage, interp, mainModule,
  mainModuleFile, packSep, withExt)
import Language.Drasil.Code.Imperative.Doxygen.Import (yes)

-- | Name options for Java files.
jNameOpts :: NameOpts
jNameOpts :: NameOpts
jNameOpts = NameOpts {
  packSep :: String
packSep = String
".",
  includeExt :: Bool
includeExt = Bool
False
}

-- | Holds a Java project.
newtype JavaProject a = JP {forall a. JavaProject a -> a
unJP :: a}

instance Functor JavaProject where
  fmap :: forall a b. (a -> b) -> JavaProject a -> JavaProject b
fmap a -> b
f (JP a
x) = b -> JavaProject b
forall a. a -> JavaProject a
JP (a -> b
f a
x)

instance Applicative JavaProject where
  pure :: forall a. a -> JavaProject a
pure = a -> JavaProject a
forall a. a -> JavaProject a
JP
  (JP a -> b
f) <*> :: forall a b. JavaProject (a -> b) -> JavaProject a -> JavaProject b
<*> (JP a
x) = b -> JavaProject b
forall a. a -> JavaProject a
JP (a -> b
f a
x)

instance Monad JavaProject where
  JP a
x >>= :: forall a b. JavaProject a -> (a -> JavaProject b) -> JavaProject b
>>= a -> JavaProject b
f = a -> JavaProject b
f a
x

instance AuxiliarySym JavaProject where
  doxConfig :: String
-> SoftwareDossierState -> Verbosity -> JavaProject FileAndContents
doxConfig = JavaProject Doc
-> String
-> SoftwareDossierState
-> Verbosity
-> JavaProject FileAndContents
forall (r :: * -> *).
(AuxiliarySym r, Applicative r) =>
r Doc
-> String -> SoftwareDossierState -> Verbosity -> r FileAndContents
G.doxConfig JavaProject Doc
forall (r :: * -> *). AuxiliarySym r => r Doc
optimizeDox
  readMe :: ReadMeInfo -> JavaProject FileAndContents
readMe ReadMeInfo
rmi =
    ReadMeInfo -> JavaProject FileAndContents
forall (r :: * -> *).
Applicative r =>
ReadMeInfo -> r FileAndContents
G.readMe ReadMeInfo
rmi {
        langName = jName,
        langVersion = jVersion}

  optimizeDox :: JavaProject Doc
optimizeDox = Doc -> JavaProject Doc
forall a. a -> JavaProject a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Doc
yes

  makefile :: [String]
-> ImplementationType
-> [Comments]
-> SoftwareDossierState
-> ProgData
-> JavaProject FileAndContents
makefile [String]
fs ImplementationType
it [Comments]
cms = Maybe BuildConfig
-> Maybe Runnable
-> Maybe DocConfig
-> SoftwareDossierState
-> ProgData
-> JavaProject FileAndContents
forall (r :: * -> *).
Applicative r =>
Maybe BuildConfig
-> Maybe Runnable
-> Maybe DocConfig
-> SoftwareDossierState
-> ProgData
-> r FileAndContents
G.makefile ([String] -> ImplementationType -> Maybe BuildConfig
jBuildConfig [String]
fs ImplementationType
it)
    (ImplementationType -> Maybe Runnable -> Maybe Runnable
G.noRunIfLib ImplementationType
it ([String] -> Maybe Runnable
jRunnable [String]
fs)) ([Comments] -> DocConfig -> Maybe DocConfig
G.docIfEnabled [Comments]
cms DocConfig
G.doxDocConfig)

  auxHelperDoc :: JavaProject Doc -> Doc
auxHelperDoc = JavaProject Doc -> Doc
forall a. JavaProject a -> a
unJP

-- | Create a build configuration for Java files. Takes in 'FilePath's and the type of implementation.
jBuildConfig :: [FilePath] -> ImplementationType -> Maybe BuildConfig
jBuildConfig :: [String] -> ImplementationType -> Maybe BuildConfig
jBuildConfig [String]
fs ImplementationType
Program = ([CommandFragment] -> CommandFragment -> [[CommandFragment]])
-> BuildName -> BuildName -> Maybe BuildConfig
buildSingle (\[CommandFragment]
i CommandFragment
_ -> [String -> CommandFragment
asFragment String
"javac" CommandFragment -> [CommandFragment] -> [CommandFragment]
forall a. a -> [a] -> [a]
: (String -> CommandFragment) -> [String] -> [CommandFragment]
forall a b. (a -> b) -> [a] -> [b]
map
  String -> CommandFragment
asFragment ([String] -> [String]
classPath [String]
fs) [CommandFragment] -> [CommandFragment] -> [CommandFragment]
forall a. [a] -> [a] -> [a]
++ [CommandFragment]
i]) (BuildName -> String -> BuildName
withExt (BuildName -> BuildName
inCodePackage BuildName
mainModule)
  String
".class") (BuildName -> Maybe BuildConfig) -> BuildName -> Maybe BuildConfig
forall a b. (a -> b) -> a -> b
$ BuildName -> BuildName
inCodePackage BuildName
mainModuleFile
jBuildConfig [String]
fs ImplementationType
Library = ([CommandFragment]
 -> CommandFragment -> CommandFragment -> [[CommandFragment]])
-> BuildName -> BuildName -> Maybe BuildConfig
buildAllAdditionalName (\[CommandFragment]
i CommandFragment
o CommandFragment
a ->
  [String -> CommandFragment
asFragment String
"javac" CommandFragment -> [CommandFragment] -> [CommandFragment]
forall a. a -> [a] -> [a]
: (String -> CommandFragment) -> [String] -> [CommandFragment]
forall a b. (a -> b) -> [a] -> [b]
map String -> CommandFragment
asFragment ([String] -> [String]
classPath [String]
fs) [CommandFragment] -> [CommandFragment] -> [CommandFragment]
forall a. [a] -> [a] -> [a]
++ [CommandFragment]
i,
    (String -> CommandFragment) -> [String] -> [CommandFragment]
forall a b. (a -> b) -> [a] -> [b]
map String -> CommandFragment
asFragment [String
"jar", String
"-cvf"] [CommandFragment] -> [CommandFragment] -> [CommandFragment]
forall a. [a] -> [a] -> [a]
++ [CommandFragment
o, CommandFragment
a]])
  (BuildName -> Ext -> BuildName
BWithExt BuildName
BPackName (Ext -> BuildName) -> Ext -> BuildName
forall a b. (a -> b) -> a -> b
$ CommandFragment -> Ext
OtherExt (CommandFragment -> Ext) -> CommandFragment -> Ext
forall a b. (a -> b) -> a -> b
$ String -> CommandFragment
asFragment String
".jar") BuildName
BPackName

-- | Default runnable information for Java files.
jRunnable :: [FilePath] -> Maybe Runnable
jRunnable :: [String] -> Maybe Runnable
jRunnable [String]
fs = BuildName -> NameOpts -> String -> [String] -> Maybe Runnable
interp ((BuildName -> String -> BuildName)
-> String -> BuildName -> BuildName
forall a b c. (a -> b -> c) -> b -> a -> c
flip BuildName -> String -> BuildName
withExt String
".class" (BuildName -> BuildName) -> BuildName -> BuildName
forall a b. (a -> b) -> a -> b
$ BuildName -> BuildName
inCodePackage BuildName
mainModule)
  NameOpts
jNameOpts String
"java" ([String] -> [String]
classPath [String]
fs)

-- | Helper for formating file paths for use in 'jBuildConfig'.
classPath :: [FilePath] -> [String]
classPath :: [String] -> [String]
classPath [String]
fs = if [String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
fs then [] else
  [String
"-cp", String
"\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
":" ([String]
fs [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
"."]) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\""]