{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE NoImplicitPrelude #-}

module System.FilePath.FilePather.Find(
  findWith
, findDirectories
, findAll
, findAllFiles
) where

import Control.Applicative ( Applicative(pure) )
import Control.Category ( Category((.)) )
import Control.Exception ( Exception )
import Control.Lens ( view, _Wrapped )
import Control.Monad ( Monad((>>=)), filterM )
import Control.Monad.IO.Class ( MonadIO(liftIO) )
import Control.Monad.Reader ( MonadReader(local, ask) )
import Data.Bool ( Bool(True) )
import Data.Foldable ( fold )
import Data.Functor ( Functor(fmap), (<$>) )
import Data.Semigroup ( Semigroup((<>)) )
import Data.Traversable ( Traversable(traverse) )
import System.FilePath ( FilePath, (</>) )
import System.FilePath.FilePather.Directory
    ( listDirectory, doesFileExist, doesDirectoryExist )
import System.FilePath.FilePather.ReadFilePath ( ReadFilePathT )
import System.IO ( IO )
import System.IO.Unsafe( unsafeInterleaveIO )

findWith ::
  Exception e =>
  ReadFilePathT e IO Bool
  -> ReadFilePathT e IO [FilePath]
findWith :: forall e.
Exception e =>
ReadFilePathT e IO Bool -> ReadFilePathT e IO [FilePath]
findWith ReadFilePathT e IO Bool
p =
  let setl :: FilePath -> ReadFilePathT e IO a -> ReadFilePathT e IO a
setl =
        forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall (f :: * -> *) a. Applicative f => a -> f a
pure
  in  do  FilePath
z <- forall r (m :: * -> *). MonadReader r m => m r
ask
          [FilePath]
a <- forall e. Exception e => ReadFilePathT e IO [FilePath]
listDirectory
          [FilePath]
b <- forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (forall {a}.
FilePath -> ReadFilePathT e IO a -> ReadFilePathT e IO a
`setl` ReadFilePathT e IO Bool
p) ((FilePath
z FilePath -> FilePath -> FilePath
</>) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [FilePath]
a)
          [FilePath]
d <- forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (forall {a}.
FilePath -> ReadFilePathT e IO a -> ReadFilePathT e IO a
`setl` forall e. ReadFilePathT e IO Bool
doesDirectoryExist) [FilePath]
b
          case [FilePath]
d of
            [] ->
              forall (f :: * -> *) a. Applicative f => a -> f a
pure [FilePath]
b
            [FilePath]
_ ->
              do  [FilePath]
n <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall a. IO a -> IO a
unsafeInterleaveIO (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold) (forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
_Wrapped (forall e.
Exception e =>
ReadFilePathT e IO Bool -> ReadFilePathT e IO [FilePath]
findWith ReadFilePathT e IO Bool
p)) [FilePath]
d)))
                  forall (f :: * -> *) a. Applicative f => a -> f a
pure ([FilePath]
b forall a. Semigroup a => a -> a -> a
<> [FilePath]
n)

findDirectories ::
  Exception e =>
  ReadFilePathT e IO [FilePath]
findDirectories :: forall e. Exception e => ReadFilePathT e IO [FilePath]
findDirectories =
  forall e.
Exception e =>
ReadFilePathT e IO Bool -> ReadFilePathT e IO [FilePath]
findWith forall e. ReadFilePathT e IO Bool
doesDirectoryExist

findAll ::
  Exception e =>
  ReadFilePathT e IO [FilePath]
findAll :: forall e. Exception e => ReadFilePathT e IO [FilePath]
findAll =
  forall e.
Exception e =>
ReadFilePathT e IO Bool -> ReadFilePathT e IO [FilePath]
findWith (forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True)

findAllFiles ::
  Exception e =>
  ReadFilePathT e IO [FilePath]
findAllFiles :: forall e. Exception e => ReadFilePathT e IO [FilePath]
findAllFiles =
  forall e. Exception e => ReadFilePathT e IO [FilePath]
findAll forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (\FilePath
p -> forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (forall (f :: * -> *) a. Applicative f => a -> f a
pure FilePath
p) forall e. ReadFilePathT e IO Bool
doesFileExist)