content: {-# LANGUAGE RankNTypes #-}
  {-# LANGUAGE RecordWildCards #-}
  module Test.Hspec.Core.Runner.PrintSlowSpecItems (
    printSlowSpecItems
  ) where
  
  import           Prelude ()
  import           Test.Hspec.Core.Compat
  
  import           System.IO (stderr, hPutStrLn)
  
  import           Test.Hspec.Core.Util
  import           Test.Hspec.Core.Format
  
  import           Test.Hspec.Core.Clock
  import           Test.Hspec.Core.Formatters.V2 (formatLocation)
  
  data SlowItem = SlowItem {
    location :: Maybe Location
  , path :: Path
  , duration :: Int
  }
  
  printSlowSpecItems :: Int -> Format -> Format
  printSlowSpecItems n format event = do
    format event
    case event of
      Done items -> do
        let xs = slowItems n $ map toSlowItem items
        unless (null xs) $ do
          hPutStrLn stderr "\nSlow spec items:"
          mapM_ printSlowSpecItem xs
      _ -> pass
  
  toSlowItem :: (Path, Item) -> SlowItem
  toSlowItem (path, item) = SlowItem (itemLocation item)  path (toMilliseconds $ itemDuration item)
  
  slowItems :: Int -> [SlowItem] -> [SlowItem]
  slowItems n = take n . reverse . sortOn duration . filter ((/= 0) . duration)
  
  printSlowSpecItem :: SlowItem -> IO ()
  printSlowSpecItem SlowItem{..} = do
    hPutStrLn stderr $ "  " ++ maybe "" formatLocation location ++ joinPath path ++ " (" ++ show duration ++ "ms)"
  