module General.Glob(globFile, globDir) where

import General.Code


-- Find the file given directories, extensions, search
-- supports * glob key
globFile :: [FilePath] -> [String] -> FilePath -> IO [FilePath]
globFile dirs exts file = f poss
    where
        f [] = exitMessage $ ["Could not find file:"
                             , "    " ++ file
                             ,"Searched:"] ++
                             map ("    " ++) poss
        f (x:xs) = do
            y <- globFileTest x
            if null y then f xs else return y

        exts2 = "" : if hasExtension file then [] else exts
        poss = [d </> file <.> e | d <- dirs, e <- exts2]


globFileTest :: FilePath -> IO [FilePath]
globFileTest file = do
    (dir,fil) <- return $ splitFileName file
    if '*' `notElem` fil then do
        b <- doesFileExist file
        return [file | b]
     else do
        s <- getDirectoryContents $ dropTrailingPathSeparator dir
        concatMapM (f dir fil) s
    where
        f dir fil x = do
            let dirx = dir </> x
            b <- doesFileExist dirx
            return [dirx | b && globMatch fil x]


globMatch :: String -> String -> Bool
globMatch glob s | null glob = False
                 | otherwise =
        head matches `isPrefixOf` s2 && last matches `isSuffixOf` s2 && f matches s2
    where
        norm = if searchPathSeparator == ';' then lower else id
        s2 = norm s
        matches = split '*' $ norm glob

        f []     s  = True
        f (m:ms) [] = False
        f (m:ms) s  | m `isPrefixOf` s = f ms $ drop (length m) s
                    | otherwise = f (m:ms) (tail s)


-- check for existence and crash if not
globDir :: FilePath -> IO FilePath
globDir x = do
    x <- canonicalizePath x
    b <- doesDirectoryExist x
    if b then return x else
        exitMessage ["Could not find directory:"
                    , "    " ++ x]