-- |
-- Stability: experimental
--
-- This module provides access to Hspec's internals.  It is less stable than
-- other parts of the API.  For most users "Test.Hspec" is more suitable!
module Test.Hspec.Core (

-- * A type class for examples
  Example (..)
, Params (..)
, Progress
, Result (..)

-- * A writer monad for constructing specs
, SpecM
, runSpecM
, fromSpecList

-- * Internal representation of a spec tree
, SpecTree (..)
, Item (..)
, mapSpecItem
, modifyParams
, describe
, it

-- * Deprecated types and functions
, Specs
, hspecB
, hspecX
, hHspec
, hspec
) where

import           Control.Applicative
import           System.IO (Handle)

import           Test.Hspec.Core.Type
import qualified Test.Hspec.Runner as Runner
import           Test.Hspec.Runner (Summary(..), Config(..), defaultConfig)

hspecWith :: Config -> [SpecTree] -> IO Summary
hspecWith c = Runner.hspecWith c . fromSpecList

mapSpecItem :: (Item -> Item) -> Spec -> Spec
mapSpecItem f = fromSpecList . map go . runSpecM
  where
    go :: SpecTree -> SpecTree
    go spec = case spec of
      SpecItem item -> SpecItem (f item)
      SpecGroup d es -> SpecGroup d (map go es)

modifyParams :: (Params -> Params) -> Spec -> Spec
modifyParams f = mapSpecItem $ \item -> item {itemExample = \p -> (itemExample item) (f p)}

{-# DEPRECATED hspecX "use `Test.Hspec.Runner.hspec` instead" #-}     -- since 1.2.0
hspecX :: [SpecTree] -> IO ()
hspecX = hspec

{-# DEPRECATED hspec "use `Test.Hspec.Runner.hspec` instead" #-}      -- since 1.4.0
hspec :: [SpecTree] -> IO ()
hspec = Runner.hspec . fromSpecList

{-# DEPRECATED hspecB "use `Test.Hspec.Runner.hspecWith` instead" #-} -- since 1.4.0
hspecB :: [SpecTree] -> IO Bool
hspecB spec = (== 0) . summaryFailures <$> hspecWith defaultConfig spec

{-# DEPRECATED hHspec "use `Test.Hspec.Runner.hspecWith` instead" #-} -- since 1.4.0
hHspec :: Handle -> [SpecTree] -> IO Summary
hHspec h = hspecWith defaultConfig {configHandle = Left h}

{-# DEPRECATED Specs "use `[SpecTree]` instead" #-}                   -- since 1.4.0
type Specs = [SpecTree]
