-- 
-- Copyright (c) Don Stewart 2004-2008.
-- Copyright (c) Tuomo Valkonen 2004.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License as
-- published by the Free Software Foundation; either version 2 of
-- the License, or (at your option) any later version.
-- 
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- General Public License for more details.
-- 
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-- 02111-1307, USA.
-- 

module Main where

import Core     (start, readSt, shutdown)
import Tree     (SerialT(..))
import Utils    ((<+>))
import Config   (darcsinfo, help, versinfo)
import Keymap   ({-# bogus import to work around 6.4 rec modules bug #-})

import qualified Data.ByteString.Char8 as P (pack,ByteString)

import Control.Exception    (catch)

import System.IO            (hPutStrLn, stderr)
import System.Exit          (ExitCode(..), exitWith)
import System.Posix.Signals (installHandler, sigTERM, sigPIPE, sigINT, sigHUP
                            ,sigALRM, sigABRT, Handler(Ignore, Default, Catch))

import System.Environment   (getArgs)

-- ---------------------------------------------------------------------
-- | Set up the signal handlers

--
-- Notes on setStoppedChildFlag:
--      If this bit is set when installing a catching function for the SIGCHLD
--      signal, the SIGCHLD signal will be generated only when a child process
--      exits, not when a child process stops.
--
-- setStoppedChildFlag True
--
initSignals :: IO ()
initSignals = do 

    -- ignore
    flip mapM_ [sigPIPE, sigALRM] 
               (\sig -> installHandler sig Ignore Nothing)

    -- and exit if we get the following:
    flip mapM_ [sigINT, sigHUP, sigABRT, sigTERM] $ \sig -> do
            installHandler sig (Catch (do
                Control.Exception.catch (shutdown Nothing) (\f -> hPutStrLn stderr (show f))
                exitWith (ExitFailure 1) )) Nothing

releaseSignals :: IO ()
releaseSignals =
    flip mapM_ [sigINT, sigPIPE, sigHUP, sigABRT, sigTERM] 
               (\sig -> installHandler sig Default Nothing)

------------------------------------------------------------------------
-- | Argument parsing.

-- usage string.
usage :: [String]
usage = ["Usage: hmp3 [-Vh] [FILE|DIR ...]"
        ,"-V  --version  Show version information"
        ,"-h  --help     Show this help"]

-- | Parse the args
do_args :: [P.ByteString] -> IO (Either SerialT [P.ByteString])
do_args []  = do    -- attempt to read db
    x <- readSt
    case x of
        Nothing -> do mapM_ putStrLn usage; exitWith ExitSuccess
        Just st -> return $ Left st

do_args [s] | s == P.pack "-V"  || s == P.pack "--version"
            = do putStrLn (versinfo <+> help); putStrLn darcsinfo; exitWith ExitSuccess
            | s == P.pack "-h"  || s == P.pack "--help"
            = do putStrLn (versinfo <+> help); mapM_ putStrLn usage; exitWith ExitSuccess

do_args xs = return $ Right xs

-- ---------------------------------------------------------------------
-- | Static main. This is the front end to the statically linked
-- application, and the real front end, in a sense. 'dynamic_main' calls
-- this after setting preferences passed from the boot loader.
--
-- Initialise the ui getting an initial editor state, set signal
-- handlers, then jump to ui event loop with the state.
--
main :: IO ()
main = do
    args  <- return . map P.pack =<< getArgs
    files <- do_args args
    initSignals
    start files -- never returns

