-- Copyright: 2009 Dino Morelli
-- License: BSD3 (see LICENSE)
-- Author: Dino Morelli <dino@ui3.info>

{-# LANGUAGE FlexibleContexts #-}

module Erbu.Common
   ( Options (..), defaultOptions
   , Env (..), Erbu, runErbu
   , assessExitCode, exitFailWithMsg, reportFailureLog
   , turnOffBuffering
   )
   where

import Control.Monad.Error
import Control.Monad.Reader
import System.Exit ( ExitCode (..), exitWith )
import System.IO ( BufferMode (..) , hSetBuffering , stdout, stderr )
import Text.Printf ( printf )

import Erbu.Conf ( ConfMap )
import Erbu.Log ( LogEvent (..), logMsg )


data Options = Options
   { optHelp :: Bool
   , optNoAction :: Bool
   , optSampleConf :: Bool
   , optUmount :: Bool
   }


defaultOptions :: Options
defaultOptions = Options
   { optHelp = False
   , optNoAction = False
   , optSampleConf = False
   , optUmount = False
   }


{- Custom monad transformer stack: ErrorT, ReaderT, IO
-}

data Env = Env
   { envOptions :: Options
   , envConfig :: ConfMap
   }

type Erbu a = ErrorT String (ReaderT Env IO) a

runErbu :: r -> ErrorT e (ReaderT r IO) a -> IO (Either e a)
runErbu env comp = runReaderT (runErrorT comp) env


assessExitCode :: (MonadError String m) =>
   String -> ExitCode -> m ()
assessExitCode name (ExitFailure code) = throwError
   $ printf "%s command failed, exit code: %d" name code
assessExitCode _    _                  = return ()


exitFailWithMsg :: String -> IO a
exitFailWithMsg err = do
   putStrLn err
   exitWith $ ExitFailure 1


reportFailureLog :: String -> IO ExitCode
reportFailureLog err = do
   logMsg ERROR err
   return $ ExitFailure 1


-- No buffering, it messes with the order of output
turnOffBuffering :: IO ()
turnOffBuffering = 
   mapM_ (flip hSetBuffering NoBuffering) [ stdout, stderr ]

