{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PostfixOperators #-}

-- | The logic to render C# auxiliary files is contained in this module
module Language.Drasil.Code.Imperative.GOOL.LanguageRenderer.CSharpRenderer (
  CSharpProject(..)
) where

import Language.Drasil.Choices (ImplementationType(..))
import Language.Drasil.Code.Imperative.GOOL.ClassInterface (ReadMeInfo(..),
  PackageSym(..), AuxiliarySym(..))
import qualified 
  Language.Drasil.Code.Imperative.GOOL.LanguageRenderer.LanguagePolymorphic as 
  G (doxConfig, readMe, sampleInput, makefile, noRunIfLib, doxDocConfig, 
  docIfEnabled)
import Language.Drasil.Code.Imperative.GOOL.Data (AuxData(..), ad, PackData(..),
  packD)
import Language.Drasil.Code.Imperative.Build.AST (BuildConfig, Runnable, 
  asFragment, buildAll, nativeBinary, osClassDefault, executable, sharedLibrary)
import Language.Drasil.Code.Imperative.Doxygen.Import (no)

import GOOL.Drasil (onCodeList, csName, csVersion)

import Prelude hiding (break,print,(<>),sin,cos,tan,floor)
import qualified Prelude as P ((<>))
import Text.PrettyPrint.HughesPJ (Doc)

-- | Holds a C# project.
newtype CSharpProject a = CSP {CSharpProject a -> a
unCSP :: a}

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

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

instance Monad CSharpProject where
  return :: a -> CSharpProject a
return = a -> CSharpProject a
forall a. a -> CSharpProject a
CSP
  CSP x :: a
x >>= :: CSharpProject a -> (a -> CSharpProject b) -> CSharpProject b
>>= f :: a -> CSharpProject b
f = a -> CSharpProject b
f a
x

instance PackageSym CSharpProject where
  type Package CSharpProject = PackData
  package :: ProgData
-> [CSharpProject (Auxiliary CSharpProject)]
-> CSharpProject (Package CSharpProject)
package p :: ProgData
p = ([AuxData] -> PackData)
-> [CSharpProject AuxData] -> CSharpProject PackData
forall (m :: * -> *) a b. Monad m => ([a] -> b) -> [m a] -> m b
onCodeList (ProgData -> [AuxData] -> PackData
packD ProgData
p)

instance AuxiliarySym CSharpProject where
  type Auxiliary CSharpProject = AuxData
  type AuxHelper CSharpProject = Doc
  doxConfig :: String
-> GOOLState
-> Verbosity
-> CSharpProject (Auxiliary CSharpProject)
doxConfig = CSharpProject (AuxHelper CSharpProject)
-> String
-> GOOLState
-> Verbosity
-> CSharpProject (Auxiliary CSharpProject)
forall (r :: * -> *).
AuxiliarySym r =>
r (AuxHelper r)
-> String -> GOOLState -> Verbosity -> r (Auxiliary r)
G.doxConfig CSharpProject (AuxHelper CSharpProject)
forall (r :: * -> *). AuxiliarySym r => r (AuxHelper r)
optimizeDox
  readMe :: ReadMeInfo -> CSharpProject (Auxiliary CSharpProject)
readMe rmi :: ReadMeInfo
rmi =
    ReadMeInfo -> CSharpProject (Auxiliary CSharpProject)
forall (r :: * -> *).
AuxiliarySym r =>
ReadMeInfo -> r (Auxiliary r)
G.readMe ReadMeInfo
rmi {
        langName :: String
langName = String
csName,
        langVersion :: String
langVersion = String
csVersion,
        invalidOS :: Maybe String
invalidOS = String -> Maybe String
forall a. a -> Maybe a
Just "All OS's except Windows"}
  sampleInput :: ChunkDB
-> DataDesc -> [Expr] -> CSharpProject (Auxiliary CSharpProject)
sampleInput = ChunkDB
-> DataDesc -> [Expr] -> CSharpProject (Auxiliary CSharpProject)
forall (r :: * -> *).
AuxiliarySym r =>
ChunkDB -> DataDesc -> [Expr] -> r (Auxiliary r)
G.sampleInput

  optimizeDox :: CSharpProject (AuxHelper CSharpProject)
optimizeDox = Doc -> CSharpProject Doc
forall (m :: * -> *) a. Monad m => a -> m a
return Doc
no

  makefile :: [String]
-> ImplementationType
-> [Comments]
-> GOOLState
-> ProgData
-> CSharpProject (Auxiliary CSharpProject)
makefile fs :: [String]
fs it :: ImplementationType
it cms :: [Comments]
cms = Maybe BuildConfig
-> Maybe Runnable
-> Maybe DocConfig
-> GOOLState
-> ProgData
-> CSharpProject (Auxiliary CSharpProject)
forall (r :: * -> *).
AuxiliarySym r =>
Maybe BuildConfig
-> Maybe Runnable
-> Maybe DocConfig
-> GOOLState
-> ProgData
-> r (Auxiliary r)
G.makefile ([String] -> ImplementationType -> Maybe BuildConfig
csBuildConfig [String]
fs ImplementationType
it) 
    (ImplementationType -> Maybe Runnable -> Maybe Runnable
G.noRunIfLib ImplementationType
it Maybe Runnable
csRunnable) ([Comments] -> DocConfig -> Maybe DocConfig
G.docIfEnabled [Comments]
cms DocConfig
G.doxDocConfig)

  auxHelperDoc :: CSharpProject (AuxHelper CSharpProject) -> Doc
auxHelperDoc = CSharpProject (AuxHelper CSharpProject) -> Doc
forall a. CSharpProject a -> a
unCSP
  auxFromData :: String -> Doc -> CSharpProject (Auxiliary CSharpProject)
auxFromData fp :: String
fp d :: Doc
d = AuxData -> CSharpProject (Auxiliary CSharpProject)
forall (m :: * -> *) a. Monad m => a -> m a
return (AuxData -> CSharpProject (Auxiliary CSharpProject))
-> AuxData -> CSharpProject (Auxiliary CSharpProject)
forall a b. (a -> b) -> a -> b
$ String -> Doc -> AuxData
ad String
fp Doc
d

-- | Create a build configuration for C# files. Takes in 'FilePath's and the type of implementation.
csBuildConfig :: [FilePath] -> ImplementationType -> Maybe BuildConfig
csBuildConfig :: [String] -> ImplementationType -> Maybe BuildConfig
csBuildConfig fs :: [String]
fs it :: ImplementationType
it = ([CommandFragment] -> CommandFragment -> [[CommandFragment]])
-> BuildName -> Maybe BuildConfig
buildAll (\i :: [CommandFragment]
i o :: CommandFragment
o -> [String -> String -> String -> CommandFragment
osClassDefault "CSC" "csc" "mcs" 
  CommandFragment -> [CommandFragment] -> [CommandFragment]
forall a. a -> [a] -> [a]
: ImplementationType -> [CommandFragment]
target ImplementationType
it [CommandFragment] -> [CommandFragment] -> [CommandFragment]
forall a. [a] -> [a] -> [a]
++ [String -> CommandFragment
asFragment "-out:" CommandFragment -> CommandFragment -> CommandFragment
forall a. Semigroup a => a -> a -> a
P.<> CommandFragment
o] [CommandFragment] -> [CommandFragment] -> [CommandFragment]
forall a. [a] -> [a] -> [a]
++ (String -> CommandFragment) -> [String] -> [CommandFragment]
forall a b. (a -> b) -> [a] -> [b]
map (String -> CommandFragment
asFragment (String -> CommandFragment)
-> (String -> String) -> String -> CommandFragment
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ("-r:" String -> String -> String
forall a. [a] -> [a] -> [a]
++)) [String]
fs
  [CommandFragment] -> [CommandFragment] -> [CommandFragment]
forall a. [a] -> [a] -> [a]
++ [CommandFragment]
i]) (ImplementationType -> BuildName
outName ImplementationType
it)
  where target :: ImplementationType -> [CommandFragment]
target Library = [String -> CommandFragment
asFragment "-t:library"]
        target Program = []
        outName :: ImplementationType -> BuildName
outName Library = BuildName
sharedLibrary
        outName Program = BuildName
executable

-- | Default runnable information for C# files.
csRunnable :: Maybe Runnable
csRunnable :: Maybe Runnable
csRunnable = Maybe Runnable
nativeBinary