module Main where

import           Conduit.Simple as S
import           Control.Exception
import           Criterion.Main
import           Data.Conduit as C
import           Data.Conduit.Combinators as C
import           Fusion as F
import           Pipes as P
import qualified Pipes.Prelude as P
import           Test.Hspec
import           Test.Hspec.Expectations

main :: IO ()
main = do
    hspec $ do
        describe "basic tests" $
            it "passes tests" $ True `shouldBe` True

    defaultMain [
        bgroup "basic" [ -- bench "pipes"          $ nfIO pipes_basic
                       -- ,
                         bench "conduit"        $ nfIO conduit_basic
                       , -- bench "simple-conduit" $ nfIO simple_conduit_basic
                       -- ,
                         bench "fusion"         $ nfIO fusion_basic
                       , bench "conduit"        $ nfIO conduit_basic
                       , bench "fusion"         $ nfIO fusion_basic
                       ]
        ]

pipes_basic :: IO Int
pipes_basic = do
    xs <- P.toListM $ P.each [1..1000000]
      P.>-> P.filter even
      P.>-> P.map (+1)
      P.>-> P.drop 1000
      P.>-> P.map (+1)
      P.>-> P.filter (\x -> x `mod` 2 == 0)
    assert (Prelude.length xs == 499000) $
        return (Prelude.length xs)

conduit_basic :: IO Int
conduit_basic = do
    xs <-   C.yieldMany [1..1000000]
      C.$= C.filter even
      C.$= C.map ((+1) :: Int -> Int)
      C.$= (C.drop 1000 >> C.awaitForever C.yield)
      C.$= C.map ((+1) :: Int -> Int)
      C.$= C.filter (\x -> x `mod` 2 == 0)
      C.$$ C.sinkList
    assert (Prelude.length xs == 499000) $
        return (Prelude.length (xs :: [Int]))

simple_conduit_basic :: IO Int
simple_conduit_basic = do
    xs <-   S.sourceList [1..1000000]
      S.$= S.filterC even
      S.$= S.mapC ((+1) :: Int -> Int)
      S.$= S.dropC 1000
      S.$= S.mapC ((+1) :: Int -> Int)
      S.$= S.filterC (\x -> x `mod` 2 == 0)
      S.$$ S.sinkList
    assert (Prelude.length xs == 499000) $
        return (Prelude.length (xs :: [Int]))

fusion_basic :: IO Int
fusion_basic = do
    xs <- F.toList $ F.each [1..1000000]
      F.>-> F.filter even
      F.>-> F.map (+1)
      F.>-> F.drop 1000
      F.>-> F.map (+1)
      F.>-> F.filter (\x -> x `mod` 2 == 0)
    assert (Prelude.length xs == 499000) $
        return (Prelude.length (xs :: [Int]))
