{-# language LambdaCase #-}
module Tempered.Options
  ( EnvVars
  , getProjectOptions
  ) where

import Control.Monad

import Data.Yaml as Y
import qualified Data.Map as M
import Data.Maybe
import Data.List

import System.FilePath
import System.Directory
import System.Exit

type EnvVars = [(String, String)]
type EnvMap = M.Map String String

-- | Given a directory tries to find env.yaml recursively upwards;
-- parses `EnvMap` from the file if found.
getProjectOptions :: FilePath -> IO EnvMap
getProjectOptions path = do
  mProjSettingsFile <- findProjSettings path
  mOptions <- traverse optionsFromFilename mProjSettingsFile
  return $ fromMaybe mempty mOptions

-- Retrieve an EnvMap from a yaml file
optionsFromFilename :: FilePath -> IO EnvMap
optionsFromFilename = Y.decodeFileEither >=>
  \case
    Left err -> die . prettyPrintParseException $ err
    Right options -> return options

-- Try to find an 'env.yaml' file.
findProjSettings :: FilePath -> IO (Maybe FilePath)
findProjSettings fpath = do
  absPath <- makeAbsolute fpath
  let searchPaths = (</> "env.yaml") <$> recurseUp absPath
  listToMaybe <$> filterM doesFileExist searchPaths

-- Get all parent directories of a directory path.
recurseUp :: FilePath -> [FilePath]
recurseUp = unfoldr go
  where
    go "/" =  Nothing
    go path = Just (path, takeDirectory path)