module Mensam.Server.Application.Environment.Class where

import Mensam.Server.Environment

import Control.Monad.Trans
import Control.Monad.Trans.Compose
import Control.Monad.Trans.Elevator
import Data.Kind
import Data.Singletons
import GHC.TypeLits

type MonadEnvironment :: (Type -> Type) -> Constraint
class Monad m => MonadEnvironment m where
  environmentVariable ::
    forall envVar.
    SingI envVar =>
    ProxyEnvVarName (EnvVarName envVar) ->
    m (EnvVarValue envVar)

instance
  ( Monad (t m)
  , MonadTrans t
  , MonadEnvironment m
  ) =>
  MonadEnvironment (Elevator t m)
  where
  environmentVariable :: forall (envVar :: EnvVar).
SingI envVar =>
ProxyEnvVarName (EnvVarName envVar)
-> Elevator t m (EnvVarValue envVar)
environmentVariable = m (EnvVarValue envVar) -> Elevator t m (EnvVarValue envVar)
forall (m :: * -> *) a. Monad m => m a -> Elevator t m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (EnvVarValue envVar) -> Elevator t m (EnvVarValue envVar))
-> (ProxyEnvVarName (EnvVarName envVar) -> m (EnvVarValue envVar))
-> ProxyEnvVarName (EnvVarName envVar)
-> Elevator t m (EnvVarValue envVar)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProxyEnvVarName (EnvVarName envVar) -> m (EnvVarValue envVar)
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

deriving via
  Elevator t1 ((t2 :: (Type -> Type) -> Type -> Type) m)
  instance
  {-# OVERLAPPABLE #-}
    ( Monad (t1 (t2 m))
    , MonadTrans t1
    , MonadEnvironment (t2 m)
    ) =>
    MonadEnvironment (ComposeT t1 t2 m)

type ProxyEnvVarName :: Symbol -> Type
data ProxyEnvVarName name = EnvVar