module ServantSerf.Directory where

import qualified ServantSerf.Type.Depth as Depth
import qualified System.Directory as Directory
import qualified System.FilePath as FilePath

list :: Depth.Depth -> FilePath -> IO [FilePath]
list :: Depth -> FilePath -> IO [FilePath]
list Depth
depth = case Depth
depth of
  Depth
Depth.Deep -> FilePath -> IO [FilePath]
listDeep
  Depth
Depth.Shallow -> FilePath -> IO [FilePath]
listShallow

listDeep :: FilePath -> IO [FilePath]
listDeep :: FilePath -> IO [FilePath]
listDeep FilePath
directory = do
  [FilePath]
entries <- FilePath -> IO [FilePath]
listShallow FilePath
directory
  [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[FilePath]] -> [FilePath]) -> IO [[FilePath]] -> IO [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FilePath -> IO [FilePath]) -> [FilePath] -> IO [[FilePath]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM FilePath -> IO [FilePath]
listDeepHelper [FilePath]
entries

listDeepHelper :: FilePath -> IO [FilePath]
listDeepHelper :: FilePath -> IO [FilePath]
listDeepHelper FilePath
entry = do
  Bool
isDirectory <- FilePath -> IO Bool
Directory.doesDirectoryExist FilePath
entry
  if Bool
isDirectory then FilePath -> IO [FilePath]
listDeep FilePath
entry else [FilePath] -> IO [FilePath]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [FilePath
entry]

listShallow :: FilePath -> IO [FilePath]
listShallow :: FilePath -> IO [FilePath]
listShallow FilePath
directory = do
  [FilePath]
entries <- FilePath -> IO [FilePath]
Directory.listDirectory FilePath
directory
  [FilePath] -> IO [FilePath]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([FilePath] -> IO [FilePath]) -> [FilePath] -> IO [FilePath]
forall a b. (a -> b) -> a -> b
$ (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (FilePath -> FilePath -> FilePath
FilePath.combine FilePath
directory) [FilePath]
entries