-- | A 'Loader' that searches an area of the filesystem for modules
-- matching the given module name, and results in the textual contents
-- of that module file.
--
-- Non-IO errors are reported as 'LoadRefusal'.  Use
-- 'Ermine.Loader.Core.loaded' and 'withExceptT' to translate this to
-- a monoidal type (e.g. '[]') for combination with other loaders.
filesystemLoader :: (MonadIO m, MonadError LoadRefusal m) =>
                    P.FilePath     -- ^ Filesystem root to start the search.
                    -> String      -- ^ File extension.
                    -> Loader Freshness m Text Text
filesystemLoader root ext =
  testBasedCacheLoader pathName
      (\pn -> trapNoSuchThing pn . TIO.readFile $ pn)
      (\pn -> liftM Freshness . trapNoSuchThing pn
              . getModificationTime $ pn)
      ((/=) `on` modTime)
  where pathName = hoistEither . runExcept
                   . fmap (\n -> root </> n <.> ext)
                   . moduleFileName
        trapNoSuchThing pn = hoistEither <=< liftIO
                           . (lifted._Left .~ FileNotFound pn)
                           . tryJust (^? errorType._NoSuchThing)
filesystemLoader :: (MonadIO m, MonadError LoadRefusal m) =>
                    P.FilePath     -- ^ Filesystem root to start the search.
                    -> String      -- ^ File extension.
                    -> Loader Freshness m Text Text
filesystemLoader root ext =
  testBasedCacheLoader pathName
      (\pn -> trapNoSuchThing pn . TIO.readFile $ pn)
      (\pn -> liftM Freshness . trapNoSuchThing pn
              . getModificationTime $ pn)
      ((/=) `on` modTime)
  where pathName = hoistEither . runExcept
                   . fmap (\n -> root </> n <.> ext)
                   . moduleFileName
        trapNoSuchThing pn = hoistEither <=< liftIO
                           . (lifted._Left .~ FileNotFound pn)
                           . tryJust (^? errorType._NoSuchThing)
filesystemLoader root ext =
  testBasedCacheLoader pathName
      (\pn -> trapNoSuchThing pn . TIO.readFile $ pn)
      (\pn -> liftM Freshness . trapNoSuchThing pn
              . getModificationTime $ pn)
      ((/=) `on` modTime)
  where pathName = hoistEither . runExcept
                   . fmap (\n -> root </> n <.> ext)
                   . moduleFileName
        trapNoSuchThing pn = hoistEither <=< liftIO
                           . (lifted._Left .~ FileNotFound pn)
                           . tryJust (^? errorType._NoSuchThing)