{-|
Module      : Headroom.Command.Gen
Description : Handler for the @gen@ command.
Copyright   : (c) 2019-2020 Vaclav Svejcar
License     : BSD-3
Maintainer  : vaclav.svejcar@gmail.com
Stability   : experimental
Portability : POSIX

The @gen@ command is responsible for generating various files requied by
/Headroom/, such as /YAML/ configuration stubs or /Mustache/ license templates.
Run /Headroom/ using the @headroom gen --help@ to see available options.
-}
{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Headroom.Command.Gen
  ( commandGen
  , parseGenMode
  )
where


import           Headroom.Command.Utils         ( bootstrap )
import           Headroom.Embedded              ( configFileStub
                                                , licenseTemplate
                                                )
import           Headroom.Types                 ( ApplicationError(..)
                                                , Command(..)
                                                , CommandGenError(..)
                                                , CommandGenOptions(..)
                                                , GenMode(..)
                                                )
import           Prelude                        ( putStrLn )
import           RIO


data Env = Env
  { Env -> LogFunc
envLogFunc    :: !LogFunc           -- ^ logging function
  , Env -> CommandGenOptions
envGenOptions :: !CommandGenOptions -- ^ options
  }

instance HasLogFunc Env where
  logFuncL :: (LogFunc -> f LogFunc) -> Env -> f Env
logFuncL = (Env -> LogFunc) -> (Env -> LogFunc -> Env) -> Lens' Env LogFunc
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Env -> LogFunc
envLogFunc (\x :: Env
x y :: LogFunc
y -> Env
x { envLogFunc :: LogFunc
envLogFunc = LogFunc
y })

env' :: CommandGenOptions -> LogFunc -> IO Env
env' :: CommandGenOptions -> LogFunc -> IO Env
env' opts :: CommandGenOptions
opts logFunc :: LogFunc
logFunc = Env -> IO Env
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Env -> IO Env) -> Env -> IO Env
forall a b. (a -> b) -> a -> b
$ $WEnv :: LogFunc -> CommandGenOptions -> Env
Env { envLogFunc :: LogFunc
envLogFunc = LogFunc
logFunc, envGenOptions :: CommandGenOptions
envGenOptions = CommandGenOptions
opts }

-- | Parses 'GenMode' from combination of options from given 'Command'.
parseGenMode :: MonadThrow m
             => Command      -- ^ command from which to parse the 'GenMode'
             -> m GenMode    -- ^ parsed 'GenMode'
parseGenMode :: Command -> m GenMode
parseGenMode = \case
  Gen True  Nothing        -> GenMode -> m GenMode
forall (f :: * -> *) a. Applicative f => a -> f a
pure GenMode
GenConfigFile
  Gen False (Just license :: (LicenseType, FileType)
license) -> GenMode -> m GenMode
forall (f :: * -> *) a. Applicative f => a -> f a
pure (GenMode -> m GenMode) -> GenMode -> m GenMode
forall a b. (a -> b) -> a -> b
$ (LicenseType, FileType) -> GenMode
GenLicense (LicenseType, FileType)
license
  _                        -> ApplicationError -> m GenMode
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (ApplicationError -> m GenMode) -> ApplicationError -> m GenMode
forall a b. (a -> b) -> a -> b
$ CommandGenError -> ApplicationError
CommandGenError CommandGenError
NoGenModeSelected

-- | Handler for /Generator/ command.
commandGen :: CommandGenOptions -- ^ /Generator/ command options
           -> IO ()             -- ^ execution result
commandGen :: CommandGenOptions -> IO ()
commandGen opts :: CommandGenOptions
opts = (LogFunc -> IO Env) -> Bool -> RIO Env () -> IO ()
forall env a. (LogFunc -> IO env) -> Bool -> RIO env a -> IO a
bootstrap (CommandGenOptions -> LogFunc -> IO Env
env' CommandGenOptions
opts) Bool
False (RIO Env () -> IO ()) -> RIO Env () -> IO ()
forall a b. (a -> b) -> a -> b
$ case CommandGenOptions -> GenMode
cgoGenMode CommandGenOptions
opts of
  GenConfigFile             -> IO () -> RIO Env ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ()
printConfigFile
  GenLicense (lType :: LicenseType
lType, fType :: FileType
fType) -> IO () -> RIO Env ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> RIO Env ()) -> (String -> IO ()) -> String -> RIO Env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO ()
putStrLn (String -> RIO Env ()) -> String -> RIO Env ()
forall a b. (a -> b) -> a -> b
$ LicenseType -> FileType -> String
forall a. IsString a => LicenseType -> FileType -> a
licenseTemplate LicenseType
lType FileType
fType

printConfigFile :: IO ()
printConfigFile :: IO ()
printConfigFile = String -> IO ()
putStrLn String
forall a. IsString a => a
configFileStub