module Cfg.Env where

import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.List (intersperse)
import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.IO (writeFile)
import Data.Tree (Tree)
import System.Environment (lookupEnv)
import Tree.Append (mayAppendLeafA')
import Prelude hiding (writeFile)
import Cfg.Parser
import Cfg.Source (RootConfig, toRootConfig)
import Cfg
import Cfg.Env.Keys

-- | @since 0.0.1.0
envSourceSep
  :: forall m
   . (MonadFail m, MonadIO m)
  => Text
  -> Tree Text
  -> m (Tree Text)
envSourceSep :: forall (m :: * -> *).
(MonadFail m, MonadIO m) =>
Text -> Tree Text -> m (Tree Text)
envSourceSep Text
sep = ([Text] -> m (Maybe Text)) -> [Text] -> Tree Text -> m (Tree Text)
forall (f :: * -> *) a.
Applicative f =>
([a] -> f (Maybe a)) -> [a] -> Tree a -> f (Tree a)
mayAppendLeafA' [Text] -> m (Maybe Text)
getLeafFromEnv []
 where
  getLeafFromEnv :: [Text] -> m (Maybe Text)
  getLeafFromEnv :: [Text] -> m (Maybe Text)
getLeafFromEnv [Text]
keys = do
    let
      key :: Text
key = (Text -> Text -> Text) -> Text -> [Text] -> Text
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((Text -> Text -> Text) -> Text -> Text -> Text
forall a b c. (a -> b -> c) -> b -> a -> c
flip Text -> Text -> Text
forall a. Monoid a => a -> a -> a
mappend) Text
"" ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
intersperse Text
sep [Text]
keys

    IO (Maybe Text) -> m (Maybe Text)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe Text) -> m (Maybe Text))
-> IO (Maybe Text) -> m (Maybe Text)
forall a b. (a -> b) -> a -> b
$ ((String -> Text) -> Maybe String -> Maybe Text
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> Text
T.pack) (Maybe String -> Maybe Text)
-> IO (Maybe String) -> IO (Maybe Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> IO (Maybe String)
lookupEnv (String -> IO (Maybe String)) -> String -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
key)

-- | @since 0.0.1.0
envSource :: (MonadFail m, MonadIO m) => Tree Text -> m (Tree Text)
envSource :: forall (m :: * -> *).
(MonadFail m, MonadIO m) =>
Tree Text -> m (Tree Text)
envSource = Text -> Tree Text -> m (Tree Text)
forall (m :: * -> *).
(MonadFail m, MonadIO m) =>
Text -> Tree Text -> m (Tree Text)
envSourceSep Text
"_"

-- | @since 0.0.1.0
printDotEnv' :: FilePath -> Text -> Tree Text -> IO ()
printDotEnv' :: String -> Text -> Tree Text -> IO ()
printDotEnv' String
path Text
sep = String -> Text -> IO ()
writeFile String
path (Text -> IO ()) -> (Tree Text -> Text) -> Tree Text -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> [Text] -> Text
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (\Text
line -> Text
"export " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
line Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"=\n") ([Text] -> Text) -> (Tree Text -> [Text]) -> Tree Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Tree Text -> [Text]
showEnvKeys' Text
sep

-- | @since 0.0.1.0
getEnvConfigSep :: (MonadFail m, MonadIO m, RootConfig a, RootParser a) => Text -> m (Either ConfigParseError a)
getEnvConfigSep :: forall (m :: * -> *) a.
(MonadFail m, MonadIO m, RootConfig a, RootParser a) =>
Text -> m (Either ConfigParseError a)
getEnvConfigSep Text
sep = FetchSource m -> m (Either ConfigParseError a)
forall a (m :: * -> *).
(Monad m, RootConfig a, RootParser a) =>
FetchSource m -> m (Either ConfigParseError a)
getConfig (FetchSource m -> m (Either ConfigParseError a))
-> FetchSource m -> m (Either ConfigParseError a)
forall a b. (a -> b) -> a -> b
$ Text -> FetchSource m
forall (m :: * -> *).
(MonadFail m, MonadIO m) =>
Text -> Tree Text -> m (Tree Text)
envSourceSep Text
sep

-- | @since 0.0.1.0
getEnvConfig :: (MonadFail m, MonadIO m, RootConfig a, RootParser a) => m (Either ConfigParseError a)
getEnvConfig :: forall (m :: * -> *) a.
(MonadFail m, MonadIO m, RootConfig a, RootParser a) =>
m (Either ConfigParseError a)
getEnvConfig = FetchSource m -> m (Either ConfigParseError a)
forall a (m :: * -> *).
(Monad m, RootConfig a, RootParser a) =>
FetchSource m -> m (Either ConfigParseError a)
getConfig (FetchSource m -> m (Either ConfigParseError a))
-> FetchSource m -> m (Either ConfigParseError a)
forall a b. (a -> b) -> a -> b
$ FetchSource m
forall (m :: * -> *).
(MonadFail m, MonadIO m) =>
Tree Text -> m (Tree Text)
envSource

-- | @since 0.0.1.0
printDotEnv :: forall a. (RootConfig a) => FilePath -> IO ()
printDotEnv :: forall a. RootConfig a => String -> IO ()
printDotEnv String
path =
  String -> Text -> IO ()
writeFile String
path
    (Text -> IO ()) -> (Tree Text -> Text) -> Tree Text -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> [Text] -> Text
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (\Text
line -> Text
"export " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
line Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"=\n")
    ([Text] -> Text) -> (Tree Text -> [Text]) -> Tree Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Tree Text -> [Text]
showEnvKeys' Text
"_"
    (Tree Text -> IO ()) -> Tree Text -> IO ()
forall a b. (a -> b) -> a -> b
$ forall a. RootConfig a => Tree Text
toRootConfig @a