{-# LANGUAGE CPP, ScopedTypeVariables #-}

-- | Module for system like things in base/directory/etc, or could plausibly be added.
module General.System(module General.System, module X) where

import System.Cmd as X
import System.Directory as X
import System.Environment as X
import System.Exit as X
import System.IO as X
import System.Mem as X (performGC)

import General.Base
import qualified Control.Exception as E

#if __GLASGOW_HASKELL__ >= 612
import GHC.IO.Handle(hDuplicate,hDuplicateTo)
#endif

#ifndef mingw32_HOST_OS
import System.Posix(setFileCreationMask)
#else
setFileCreationMask :: Int -> IO Int
setFileCreationMask _ = return 0
#endif


isWindows :: Bool
#ifdef mingw32_HOST_OS
isWindows = True
#else
isWindows = False
#endif


removeFile_ x = removeFile x `E.catch` \(_ :: E.SomeException) -> return ()


withDirectory dir cmd = E.bracket
    (do x <- getCurrentDirectory; setCurrentDirectory dir; return x)
    setCurrentDirectory
    (const cmd)


withModeGlobalRead :: IO () -> IO ()
withModeGlobalRead act = E.bracket
    (setFileCreationMask 0o022)
    (\x -> setFileCreationMask x >> return ())
    (const act)


-- FIXME: This could use a lot more bracket calls!
captureOutput :: IO () -> IO (Maybe String)
#if __GLASGOW_HASKELL__ < 612
captureOutput act = return Nothing
#else
captureOutput act = do
    tmp <- getTemporaryDirectory
    (f,h) <- openTempFile tmp "hoogle"
    sto <- hDuplicate stdout
    ste <- hDuplicate stderr
    hDuplicateTo h stdout
    hDuplicateTo h stderr
    hClose h
    act
    hDuplicateTo sto stdout
    hDuplicateTo ste stderr
    res <- readFile' f
    removeFile f
    return $ Just res
#endif


system_ :: String -> IO ()
system_ x = do
    res <- system x
    when (res /= ExitSuccess) $ error $ "System command failed: " ++ x


exitMessage :: [String] -> IO a
exitMessage msg = putStr (unlines msg) >> exitFailure


getEnvVar :: String -> IO (Maybe String)
getEnvVar x = E.catch (fmap Just $ getEnv x) (\(x :: E.SomeException) -> return Nothing)