{-|
Functions for creating project initialization applications
-}

module ProjectForge.Actions (
    createProjectTemplateAction
  , defaultTemplateActionOpts
  , TemplateLocation(..)
  , TemplateActionOpts(..)
) where

import           Blammo.Logging.Simple  (MonadLogger)
import           Control.Monad.IO.Class (MonadIO)
import           Data.Aeson             (ToJSON (toJSON))
import           ProjectForge.Get       (getProjectTemplateFromDir,
                                         getProjectTemplateFromGit)
import           ProjectForge.Get.Git   (GitURL)
import           ProjectForge.Render

-- | Location of template directory
data TemplateLocation =
    Local FilePath
  | Git GitURL
  deriving (TemplateLocation -> TemplateLocation -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TemplateLocation -> TemplateLocation -> Bool
$c/= :: TemplateLocation -> TemplateLocation -> Bool
== :: TemplateLocation -> TemplateLocation -> Bool
$c== :: TemplateLocation -> TemplateLocation -> Bool
Eq, Int -> TemplateLocation -> ShowS
[TemplateLocation] -> ShowS
TemplateLocation -> FilePath
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [TemplateLocation] -> ShowS
$cshowList :: [TemplateLocation] -> ShowS
show :: TemplateLocation -> FilePath
$cshow :: TemplateLocation -> FilePath
showsPrec :: Int -> TemplateLocation -> ShowS
$cshowsPrec :: Int -> TemplateLocation -> ShowS
Show)

{-|
Options for compiling, rendering and writing a a @'ProjectTemplate'@.
-}
newtype TemplateActionOpts = MkTemplateActionOpts {
    -- | The @'RenderTemplateOpts'@ for the action
    TemplateActionOpts -> RenderTemplateOpts
renderOpts :: RenderTemplateOpts
  }

-- | Default options
defaultTemplateActionOpts :: TemplateActionOpts
defaultTemplateActionOpts :: TemplateActionOpts
defaultTemplateActionOpts = MkTemplateActionOpts { renderOpts :: RenderTemplateOpts
renderOpts = RenderTemplateOpts
defaultRenderTemplateOpts}

{-|
Create an @IO@ action that compiles, renders, and writes a @'ProjectTemplate'@.
-}
createProjectTemplateAction :: (MonadLogger m, MonadIO m, ToJSON a) =>
     TemplateActionOpts
  -> TemplateLocation
  -> a -- ^ type which when converted via @'Data.Aeson.toJSON'@ contains values
      --    to interpolate into the @'ProjectTemplate'@.
  -> m ()
createProjectTemplateAction :: forall (m :: * -> *) a.
(MonadLogger m, MonadIO m, ToJSON a) =>
TemplateActionOpts -> TemplateLocation -> a -> m ()
createProjectTemplateAction TemplateActionOpts
opts TemplateLocation
loc a
settings = do
  let template :: m ProjectTemplate
template = case TemplateLocation
loc of
         Local FilePath
dir -> forall (m :: * -> *).
(MonadLogger m, MonadIO m) =>
FilePath -> m ProjectTemplate
getProjectTemplateFromDir FilePath
dir
         Git FilePath
url   -> forall (m :: * -> *).
(MonadLogger m, MonadIO m) =>
Maybe FilePath -> FilePath -> Maybe FilePath -> m ProjectTemplate
getProjectTemplateFromGit forall a. Maybe a
Nothing FilePath
url forall a. Maybe a
Nothing
      values :: Value
values = forall a. ToJSON a => a -> Value
toJSON a
settings

  [(FilePath, Text)]
results <- (\ProjectTemplate
x -> forall (m :: * -> *).
(MonadIO m, MonadLogger m) =>
RenderTemplateOpts
-> ProjectTemplate -> Value -> m [(FilePath, Text)]
renderProjectTemplate (TemplateActionOpts -> RenderTemplateOpts
renderOpts TemplateActionOpts
opts) ProjectTemplate
x Value
values) forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m ProjectTemplate
template

  forall (m :: * -> *).
(MonadLogger m, MonadIO m) =>
[(FilePath, Text)] -> m ()
writeTemplateResult [(FilePath, Text)]
results