#!/usr/bin/env runhaskell
import Shellish( shellish, rm_rf )
import Control.Arrow ( second )
import System.Console.CmdArgs
import System.Exit
import System.Directory
import System.IO
import Control.Monad
import Control.Monad.Trans
import Benchmark
import Config (Config(Get,Run))
import qualified Config as C
import Standard
import Download
import Data.List
import Data.Version ( showVersion )
import Paths_darcs_benchmark

help :: String
help = unlines [ "darcs-benchmark " ++ showVersion version ++ ": run standard darcs benchmarks"
               , ""
               , "Please either specify the repositories and binaries to run on like this:"
               , "$ darcs-benchmark run <binary> [binary] [/ [repository] [repository]]"
               , ""
               , "or alternatively, to run on all available repos:"
               , "$ darcs-benchmark run <binary> [binary]"
               , ""
               , "You can also create a file called 'config' in the working directory."
               , "Put two lines in it, one with list of binaries, one with list of repos:"
               , ""
               , "binary binary binary"
               , "repo repo repo"
               , ""
               , "(again, if the second line is not there, we run on all available repos)"
               , ""
               , "Thank you for benchmarking darcs!" ]

known_repos :: [String]
known_repos = [ "ghc-hashed", "darcs" ]

download_repos :: [String] -> IO ()
download_repos r = forM_ (if null r then known_repos else r) download

config :: [TestRepo] -> C.Config -> IO ([TestRepo], [TestBinary], [Benchmark ()])
config allrepos cfg = do
  case cfg of
   Get {} -> do
      download_repos (C.repos cfg)
      exitWith ExitSuccess
   Run {} -> do
     haveConf <- doesFileExist "config"
     conf <- if haveConf then lines `fmap` readFile "config"
                         else return []
     let confrepos = if length conf > 1 then (words $ conf !! 1) else []
         confbins = if length conf > 0 then words $ conf !! 0 else []
         (bins,repos) = second (drop 1) $ break (== "/") (C.extra cfg)
         userepos = map TestRepo $ if null repos then confrepos else repos
         usebins = map TestBinary $ if null bins then confbins else bins
         usetests = if C.fast cfg then fast else standard
     when (null usebins) $ do
       hPutStrLn stderr "Please specify at least one darcs binary to benchmark"
       exitWith (ExitFailure 1)
     return ( if null userepos then allrepos else userepos
            , usebins
            , usetests
            )

main :: IO ()
main = do
    cfg <- cmdArgs help C.defaultConfig
    allrepos <- do listing <- getDirectoryContents "."
                   return $ [ TestRepo $ drop 5 repo
                              | repo <- listing, repo `notElem` [".", ".."]
                                               , "repo." `isPrefixOf` repo ]
    (repos, binaries, tests) <- config allrepos cfg
    unless (null $ repos \\ allrepos) $ do
         let name r = intercalate ", " $ map (\(TestRepo x) -> x) r
         putStrLn $ "Missing repositories: " ++ name (repos \\ allrepos)
         exitWith $ ExitFailure 2
    forM binaries $ \(TestBinary bin) -> check_darcs bin
    when (null repos) $ do
         putStrLn $ "Oops, no repositories! Consider doing a darcs-benchmark get."
         putStrLn $ "(Alternatively, check that you are in the right directory.)"
         exitWith $ ExitFailure 3
    shellish $ do rm_rf "_playground"
                  res <- benchMany repos binaries tests
                  if C.dump cfg
                     then liftIO $ print res
                     else renderMany res

