    module CmdLine.Action(actionCmdLine) where

    import CmdLine.Flag
    import CmdLine.Query
    import CmdLine.Search
    import CmdLine.Files
    import CmdLine.Test
    import General.Code
    import Hoogle.All
    import Test.All
    import Text.ParserCombinators.Parsec

    import Paths_hoogle(version)
    import Data.Version(showVersion)

    actionCmdLine :: CmdQuery -> IO ()

    actionCmdLine CmdQuery{queryText = text, query = Left err} =
        exitMessage ["Parse error:", "  " ++ text
                    ,replicate (sourceColumn (errorPos err) + 1) ' ' ++ "^"
                    ,show err]

    actionCmdLine q | not $ null $ queryBadFlags q =
        exitMessage $ "Unrecognised or malformed flags:":
                      map ("  "++) (queryBadFlags q) ++
                      ["For details on correct flags pass --help"]

    actionCmdLine q | Version `elem` queryFlags q = putStr $ unlines
        ["Hoogle - (C) Neil Mitchell 2004-2008, University of York, UK"
        ,"Version " ++ showVersion version]

    actionCmdLine q | Help `elem` queryFlags q =
        putStr $ "Go to the website for full help, http://haskell.org/hoogle/\n" ++
                 "\n" ++
                 "Flag reference:\n" ++
                 flagsHelp

    actionCmdLine q | Test `elem` queryFlags q = test

    actionCmdLine q | TestFile{} `elemEnum` queryFlags q =
        mapM_ (actionTest q) [x | TestFile x <- queryFlags q]

    actionCmdLine q | Rank{} `elemEnum` queryFlags q =
        mapM_ rank [x | Rank x <- queryFlags q]

    actionCmdLine q | Convert{} `elemEnum` queryFlags q =
        mapM_ (actionConvert q) [x | Convert x <- queryFlags q]

    actionCmdLine q | Combine{} `elemEnum` queryFlags q = do
        -- TODO: Work around a bug in CmdLine.Flags, try /merge=t1;t2
        --       and you get [t1,t1,t2,t2]
        let files = nub [x | Combine x <- queryFlags q]
            outfile = headDef "default.hoo" [x | Output x <- queryFlags q]
        putStrLn $ "Combining " ++ show (length files) ++ " databases"
        combine files outfile
        when (Dump{} `elemEnum` queryFlags q) $ do
            putStrLn ""
            actionDump q outfile

    actionCmdLine q | Dump{} `elemEnum` queryFlags q = do
        dbs <- getDataBaseFiles (queryFlags q) (fromRight $ query q)
        mapM_ (actionDump q) dbs

    actionCmdLine q | not $ usefulQuery $ fromRight $ query q =
        exitMessage ["No query entered"
                    ,"Try --help for command line options"]

    actionCmdLine q = actionSearch (queryFlags q) (fromRight $ query q)

    ---------------------------------------------------------------------
    -- SPECIFIC ACTIONS

    actionDump :: CmdQuery -> FilePath -> IO ()
    actionDump q file = do
        let part = head [x | Dump x <- queryFlags q]
        d <- loadDataBase file
        putStrLn $ "File: " ++ file
        putStr $ showDataBase part d

    actionConvert :: CmdQuery -> FilePath -> IO FilePath
    actionConvert q infile = do
        let outfile = headDef (replaceExtension infile "hoo") [x | Output x <- queryFlags q]
        putStrLn $ "Converting " ++ infile
        deps <- getDataBaseFilesNoDefault (queryFlags q) (fromRight $ query q)
        convert (Debug `elem` queryFlags q) deps infile outfile
        putStrLn $ "Written " ++ outfile

        when (Dump{} `elemEnum` queryFlags q) $ do
            putStrLn ""
            actionDump q outfile
        return outfile

    actionTest :: CmdQuery -> FilePath -> IO ()
    actionTest q infile = do
        outfile <- actionConvert q{queryFlags = Debug : queryFlags q} infile
        testFile infile outfile