module Mensam.Server.Application.Configured.Acquisition where

import Mensam.Server.Application.Environment.Class
import Mensam.Server.Configuration

import Control.Monad.IO.Class
import Control.Monad.Logger.CallStack
import Data.Aeson qualified as A
import Data.Text qualified as T
import System.Posix.Files

acquireConfig ::
  (MonadIO m, MonadEnvironment m, MonadLogger m) =>
  m (Maybe Configuration)
acquireConfig :: forall (m :: * -> *).
(MonadIO m, MonadEnvironment m, MonadLogger m) =>
m (Maybe Configuration)
acquireConfig = do
  Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
logInfo Text
"Checking configuration file."
  String
configFile <- ProxyEnvVarName (EnvVarName 'EnvVarConfigFile)
-> m (EnvVarValue 'EnvVarConfigFile)
forall (envVar :: EnvVar).
SingI envVar =>
ProxyEnvVarName (EnvVarName envVar) -> m (EnvVarValue envVar)
forall (m :: * -> *) (envVar :: EnvVar).
(MonadEnvironment m, SingI envVar) =>
ProxyEnvVarName (EnvVarName envVar) -> m (EnvVarValue envVar)
environmentVariable (ProxyEnvVarName (EnvVarName 'EnvVarConfigFile)
 -> m (EnvVarValue 'EnvVarConfigFile))
-> ProxyEnvVarName (EnvVarName 'EnvVarConfigFile)
-> m (EnvVarValue 'EnvVarConfigFile)
forall a b. (a -> b) -> a -> b
$ forall (name :: Symbol). ProxyEnvVarName name
EnvVar @"MENSAM_CONFIG_FILE"
  Bool
exists <- IO Bool -> m Bool
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Bool -> m Bool) -> IO Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ String -> IO Bool
fileExist String
configFile
  if Bool
exists
    then do
      Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
logInfo Text
"Reading configuration file."
      Either String Configuration
eitherContent <- IO (Either String Configuration) -> m (Either String Configuration)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either String Configuration)
 -> m (Either String Configuration))
-> IO (Either String Configuration)
-> m (Either String Configuration)
forall a b. (a -> b) -> a -> b
$ String -> IO (Either String Configuration)
forall a. FromJSON a => String -> IO (Either String a)
A.eitherDecodeFileStrict String
configFile
      case Either String Configuration
eitherContent of
        Left String
err -> do
          Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
logError (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"Failed to read/parse configuration file: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (String -> String
forall a. Show a => a -> String
show String
err)
          Maybe Configuration -> m (Maybe Configuration)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Configuration
forall a. Maybe a
Nothing
        Right Configuration
config -> do
          Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
logInfo (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"Acquired configuration: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Configuration -> String
forall a. Show a => a -> String
show Configuration
config)
          Maybe Configuration -> m (Maybe Configuration)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Configuration -> m (Maybe Configuration))
-> Maybe Configuration -> m (Maybe Configuration)
forall a b. (a -> b) -> a -> b
$ Configuration -> Maybe Configuration
forall a. a -> Maybe a
Just Configuration
config
    else do
      Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
logError Text
"Can't find configuration file."
      Maybe Configuration -> m (Maybe Configuration)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Configuration
forall a. Maybe a
Nothing