{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilyDependencies #-}

module Mensam.Server.Environment where

import Control.Monad.Logger.CallStack
import Data.Kind
import Data.Singletons.TH
import GHC.Generics
import GHC.TypeLits
import Text.Read

type EnvVar :: Type
data EnvVar
  = EnvVarConfigFile
  | EnvVarLogColor
  | EnvVarLogFile
  | EnvVarLogLevel
  deriving stock (EnvVar
EnvVar -> EnvVar -> Bounded EnvVar
forall a. a -> a -> Bounded a
$cminBound :: EnvVar
minBound :: EnvVar
$cmaxBound :: EnvVar
maxBound :: EnvVar
Bounded, Int -> EnvVar
EnvVar -> Int
EnvVar -> [EnvVar]
EnvVar -> EnvVar
EnvVar -> EnvVar -> [EnvVar]
EnvVar -> EnvVar -> EnvVar -> [EnvVar]
(EnvVar -> EnvVar)
-> (EnvVar -> EnvVar)
-> (Int -> EnvVar)
-> (EnvVar -> Int)
-> (EnvVar -> [EnvVar])
-> (EnvVar -> EnvVar -> [EnvVar])
-> (EnvVar -> EnvVar -> [EnvVar])
-> (EnvVar -> EnvVar -> EnvVar -> [EnvVar])
-> Enum EnvVar
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: EnvVar -> EnvVar
succ :: EnvVar -> EnvVar
$cpred :: EnvVar -> EnvVar
pred :: EnvVar -> EnvVar
$ctoEnum :: Int -> EnvVar
toEnum :: Int -> EnvVar
$cfromEnum :: EnvVar -> Int
fromEnum :: EnvVar -> Int
$cenumFrom :: EnvVar -> [EnvVar]
enumFrom :: EnvVar -> [EnvVar]
$cenumFromThen :: EnvVar -> EnvVar -> [EnvVar]
enumFromThen :: EnvVar -> EnvVar -> [EnvVar]
$cenumFromTo :: EnvVar -> EnvVar -> [EnvVar]
enumFromTo :: EnvVar -> EnvVar -> [EnvVar]
$cenumFromThenTo :: EnvVar -> EnvVar -> EnvVar -> [EnvVar]
enumFromThenTo :: EnvVar -> EnvVar -> EnvVar -> [EnvVar]
Enum, EnvVar -> EnvVar -> Bool
(EnvVar -> EnvVar -> Bool)
-> (EnvVar -> EnvVar -> Bool) -> Eq EnvVar
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: EnvVar -> EnvVar -> Bool
== :: EnvVar -> EnvVar -> Bool
$c/= :: EnvVar -> EnvVar -> Bool
/= :: EnvVar -> EnvVar -> Bool
Eq, (forall x. EnvVar -> Rep EnvVar x)
-> (forall x. Rep EnvVar x -> EnvVar) -> Generic EnvVar
forall x. Rep EnvVar x -> EnvVar
forall x. EnvVar -> Rep EnvVar x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. EnvVar -> Rep EnvVar x
from :: forall x. EnvVar -> Rep EnvVar x
$cto :: forall x. Rep EnvVar x -> EnvVar
to :: forall x. Rep EnvVar x -> EnvVar
Generic, Eq EnvVar
Eq EnvVar =>
(EnvVar -> EnvVar -> Ordering)
-> (EnvVar -> EnvVar -> Bool)
-> (EnvVar -> EnvVar -> Bool)
-> (EnvVar -> EnvVar -> Bool)
-> (EnvVar -> EnvVar -> Bool)
-> (EnvVar -> EnvVar -> EnvVar)
-> (EnvVar -> EnvVar -> EnvVar)
-> Ord EnvVar
EnvVar -> EnvVar -> Bool
EnvVar -> EnvVar -> Ordering
EnvVar -> EnvVar -> EnvVar
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: EnvVar -> EnvVar -> Ordering
compare :: EnvVar -> EnvVar -> Ordering
$c< :: EnvVar -> EnvVar -> Bool
< :: EnvVar -> EnvVar -> Bool
$c<= :: EnvVar -> EnvVar -> Bool
<= :: EnvVar -> EnvVar -> Bool
$c> :: EnvVar -> EnvVar -> Bool
> :: EnvVar -> EnvVar -> Bool
$c>= :: EnvVar -> EnvVar -> Bool
>= :: EnvVar -> EnvVar -> Bool
$cmax :: EnvVar -> EnvVar -> EnvVar
max :: EnvVar -> EnvVar -> EnvVar
$cmin :: EnvVar -> EnvVar -> EnvVar
min :: EnvVar -> EnvVar -> EnvVar
Ord, ReadPrec [EnvVar]
ReadPrec EnvVar
Int -> ReadS EnvVar
ReadS [EnvVar]
(Int -> ReadS EnvVar)
-> ReadS [EnvVar]
-> ReadPrec EnvVar
-> ReadPrec [EnvVar]
-> Read EnvVar
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS EnvVar
readsPrec :: Int -> ReadS EnvVar
$creadList :: ReadS [EnvVar]
readList :: ReadS [EnvVar]
$creadPrec :: ReadPrec EnvVar
readPrec :: ReadPrec EnvVar
$creadListPrec :: ReadPrec [EnvVar]
readListPrec :: ReadPrec [EnvVar]
Read, Int -> EnvVar -> ShowS
[EnvVar] -> ShowS
EnvVar -> [Char]
(Int -> EnvVar -> ShowS)
-> (EnvVar -> [Char]) -> ([EnvVar] -> ShowS) -> Show EnvVar
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> EnvVar -> ShowS
showsPrec :: Int -> EnvVar -> ShowS
$cshow :: EnvVar -> [Char]
show :: EnvVar -> [Char]
$cshowList :: [EnvVar] -> ShowS
showList :: [EnvVar] -> ShowS
Show)

genSingletons [''EnvVar]

type EnvVarName :: EnvVar -> Symbol
type family EnvVarName envVar = name | name -> envVar where
  EnvVarName EnvVarConfigFile = "MENSAM_CONFIG_FILE"
  EnvVarName EnvVarLogColor = "MENSAM_LOG_COLOR"
  EnvVarName EnvVarLogFile = "MENSAM_LOG_FILE"
  EnvVarName EnvVarLogLevel = "MENSAM_LOG_LEVEL"

type EnvVarValue :: EnvVar -> Type
type family EnvVarValue envVar = value where
  EnvVarValue EnvVarConfigFile = FilePath
  EnvVarValue EnvVarLogFile = Maybe FilePath
  EnvVarValue EnvVarLogLevel = LogLevel
  EnvVarValue EnvVarLogColor = Bool

envVarParse :: SEnvVar envVar -> String -> Maybe (EnvVarValue envVar)
envVarParse :: forall (envVar :: EnvVar).
SEnvVar envVar -> [Char] -> Maybe (EnvVarValue envVar)
envVarParse = \case
  SEnvVar envVar
SEnvVarConfigFile -> [Char] -> Maybe [Char]
[Char] -> Maybe (EnvVarValue envVar)
forall a. a -> Maybe a
Just
  SEnvVar envVar
SEnvVarLogColor -> [Char] -> Maybe Bool
[Char] -> Maybe (EnvVarValue envVar)
forall a. Read a => [Char] -> Maybe a
readMaybe
  SEnvVar envVar
SEnvVarLogFile -> Maybe [Char] -> Maybe (Maybe [Char])
forall a. a -> Maybe a
Just (Maybe [Char] -> Maybe (Maybe [Char]))
-> ([Char] -> Maybe [Char]) -> [Char] -> Maybe (Maybe [Char])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just
  SEnvVar envVar
SEnvVarLogLevel -> [Char] -> Maybe LogLevel
[Char] -> Maybe (EnvVarValue envVar)
forall a. Read a => [Char] -> Maybe a
readMaybe

envVarDefault :: SEnvVar envVar -> EnvVarValue envVar
envVarDefault :: forall (envVar :: EnvVar). SEnvVar envVar -> EnvVarValue envVar
envVarDefault = \case
  SEnvVar envVar
SEnvVarConfigFile -> [Char]
EnvVarValue envVar
"./mensam.json"
  SEnvVar envVar
SEnvVarLogColor -> Bool
EnvVarValue envVar
True
  SEnvVar envVar
SEnvVarLogFile -> Maybe [Char]
EnvVarValue envVar
forall a. Maybe a
Nothing
  SEnvVar envVar
SEnvVarLogLevel -> LogLevel
EnvVarValue envVar
LevelDebug

envVarHelp :: [String]
envVarHelp :: [[Char]]
envVarHelp = EnvVar -> [Char]
singleEnvVarHelp (EnvVar -> [Char]) -> [EnvVar] -> [[Char]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [EnvVar
forall a. Bounded a => a
minBound .. EnvVar
forall a. Bounded a => a
maxBound]
 where
  singleEnvVarHelp :: EnvVar -> String
  singleEnvVarHelp :: EnvVar -> [Char]
singleEnvVarHelp = \case
    EnvVar
EnvVarConfigFile -> [Char]
"MENSAM_CONFIG_FILE=[FILEPATH] (filepath to a JSON configuration file)"
    EnvVar
EnvVarLogColor -> [Char]
"MENSAM_LOG_COLOR=[True|False] (toggle the color of the log)"
    EnvVar
EnvVarLogFile -> [Char]
"MENSAM_LOG_FILE=[FILEPATH] (filepath where the log will get dumped)"
    EnvVar
EnvVarLogLevel -> [Char]
"MENSAM_LOG_LEVEL=[LevelDebug|LevelInfo|LevelWarn|LevelError] (set log verbosity)"

type Environment :: Type
newtype Environment = MkEnvironment {Environment
-> forall (envVar :: EnvVar). SEnvVar envVar -> EnvVarValue envVar
getEnvironment :: forall envVar. SEnvVar envVar -> EnvVarValue envVar}