{-# LANGUAGE OverloadedStrings #-}

module E9571.ConfigReader
  ( loadConfig
  , loadConfigOrDie
  ) where

import           Data.Aeson             (FromJSON(..), eitherDecode)
import qualified Data.ByteString.Lazy   as LBS
import           System.Directory       (doesFileExist)

loadConfig :: FromJSON a => IO (Either String a)
loadConfig :: forall a. FromJSON a => IO (Either String a)
loadConfig = do
    let path :: String
path = String
"config.json"
    Bool
exists <- String -> IO Bool
doesFileExist String
path
    if Bool -> Bool
not Bool
exists
        then Either String a -> IO (Either String a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String a -> IO (Either String a))
-> Either String a -> IO (Either String a)
forall a b. (a -> b) -> a -> b
$ String -> Either String a
forall a b. a -> Either a b
Left String
"Error: config.json not found in current directory"
        else do
            ByteString
bs <- String -> IO ByteString
LBS.readFile String
path
            Either String a -> IO (Either String a)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String a -> IO (Either String a))
-> Either String a -> IO (Either String a)
forall a b. (a -> b) -> a -> b
$ (String -> Either String a)
-> (a -> Either String a) -> Either String a -> Either String a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> Either String a
forall a b. a -> Either a b
Left (String -> Either String a)
-> (String -> String) -> String -> Either String a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"JSON parse error: " String -> String -> String
forall a. [a] -> [a] -> [a]
++)) a -> Either String a
forall a b. b -> Either a b
Right (ByteString -> Either String a
forall a. FromJSON a => ByteString -> Either String a
eitherDecode ByteString
bs)

loadConfigOrDie :: FromJSON a => IO a
loadConfigOrDie :: forall a. FromJSON a => IO a
loadConfigOrDie = IO (Either String a)
forall a. FromJSON a => IO (Either String a)
loadConfig IO (Either String a) -> (Either String a -> IO a) -> IO a
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (String -> IO a) -> (a -> IO a) -> Either String a -> IO a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> IO a
forall a. String -> IO a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail a -> IO a
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure