{-# LANGUAGE FlexibleContexts #-}

module Axel.Utils.Directory where

import Control.Monad (forM)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Trans.Control (MonadBaseControl, control)

import System.Directory
  ( createDirectoryIfMissing
  , doesDirectoryExist
  , getDirectoryContents
  , getTemporaryDirectory
  , withCurrentDirectory
  )
import System.FilePath ((</>))

-- Adapted from http://book.realworldhaskell.org/read/io-case-study-a-library-for-searching-the-filesystem.html.
getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents startDir = do
  names <- getDirectoryContents startDir
  let properNames = filter (`notElem` [".", ".."]) names
  paths <-
    forM properNames $ \name -> do
      let path = startDir </> name
      isDirectory <- doesDirectoryExist path
      if isDirectory
        then getRecursiveContents path
        else pure [path]
  pure $ concat paths

withCurrentDirectoryLifted :: (MonadBaseControl IO m) => FilePath -> m a -> m a
withCurrentDirectoryLifted directory f =
  control $ \runInIO -> withCurrentDirectory directory (runInIO f)

withTempDirectory :: (MonadIO m) => (FilePath -> m a) -> m a
withTempDirectory f = do
  temporaryDirectory <- liftIO getTemporaryDirectory
  liftIO $ createDirectoryIfMissing True temporaryDirectory
  result <- f temporaryDirectory
  pure result