-----------------------------------------------------------------------------
--
-- Module      :  Control.Concurrent.Network.Process
-- Copyright   :  (C) 2010, Paul Sonkoly
-- License     :  BSD style
--
-- Maintainer  :  Paul Sonkoly
-- Stability   :  provisional
-- Portability :
--
-- |  General idea is having one dedicated master process and an arbitrary
--    number of slave processes.
--
-----------------------------------------------------------------------------

module Control.Concurrent.Network.Process
    (
    -- * Functions
      initProcess
    ) where

import System.IO
import Control.Concurrent.Network.Master
import Control.Concurrent.Network.Slave
import System.Console.GetOpt
import System.Environment
import System.Exit
import System.Log.Logger


data Options = Options
    { optMaster         :: Bool
    , optChildNum       :: Int
    , optDbgLevel       :: Priority
    }

defaultOptions = Options
    { optMaster     = False
    , optChildNum   = 1
    , optDbgLevel   = WARNING
    }

options :: [ OptDescr (Options -> IO Options) ]
options =
    [ Option "m" ["child-number"] (ReqArg
        (\ n opt -> return opt {optMaster = True, optChildNum = read n}) "[INT]")
         "Master process only: number of child processes."
    , Option "d" ["debug-level"] (ReqArg
        (\ lev opt -> return opt { optDbgLevel = read lev })
        "[DEBUG|INFO|NOTICE|WARNING|ERROR|CRITICAL|ALERT|EMERGENCY]")
        "Debug level"

    , Option "h" ["help"]
        (NoArg
            (\_ -> do
    	        prg <- getProgName
                hPutStrLn stderr (usageInfo prg options)
                exitWith ExitSuccess))
        "Show help"
    ]

-- | Convinience function. It calls either 'initMaster' or
--   'initSlave' depending on whether we have -m on the command line
--   or not. If -m is specified the following argument should be the
--   number of slaves to wait for.
--
--   Returns in the slave processes with the NC context.
--   Does not return in the master process.
initProcess :: IO NCContext
initProcess = do
    args <- getArgs
    (acts, _, msgs) <- return $ getOpt RequireOrder options args
    putStrLn $ concat msgs
    opts <- foldl (>>=) (return defaultOptions) acts

    logger <- getRootLogger
    saveGlobalLogger $ setLevel (optDbgLevel opts) logger

    if optMaster opts
        then do
            initMaster $ optChildNum opts
            exitSuccess
        else initSlave