{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}

module Main where

import Criterion.Main
import Criterion.Types
import qualified Data.ByteString.Lazy as L (readFile)
import Data.ByteString.Lazy.Char8 (ByteString)
import Data.Foldable (toList)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Parser.GraphQL as GQL
import Parser.Morpheus as Morpheus

fetchCase :: FilePath -> IO (ByteString, Text)
fetchCase x = (,) <$> L.readFile path <*> TIO.readFile path
  where
    path = "samples/" <> x <> ".gql"

fetch :: FilePath -> IO (String, (ByteString, Text))
fetch path = do
  x <- fetchCase path
  pure (typeCount x, x)

data Info = Info
  { lineCount :: Int,
    name :: String,
    src :: FilePath
  }

getFile :: Info -> IO (Info, ByteString, Text)
getFile info = do
  (b, t) <- fetchCase (src info)
  pure (info, b, t)

getFiles :: IO [(Info, ByteString, Text)]
getFiles =
  traverse
    getFile
    [ Info {lineCount = 5, name = "Huge String", src = "huge-string"},
      Info {lineCount = 94, name = "Mythology", src = "mythology"},
      Info {lineCount = 2500, name = "Many Descriptions", src = "descriptions"},
      --  Info {lineCount = 38948, name = "github", src = "github"},
      Info {lineCount = 5922, name = "Star Wars", src = "starWars"},
      Info {lineCount = 6, name = "Many Wrappers", src = "wrappers"}
    ]

typeCount :: (ByteString, Text) -> String
typeCount (bs, txt) =
  "morpheus("
    <> show (Morpheus.countParsedTypes bs)
    <> ") - gql("
    <> show (GQL.countParsedTypes txt)
    <> ")"

benchText :: (Text -> Text) -> [(Info, ByteString, Text)] -> [Benchmark]
benchText f = map (\(Info {name}, _, t) -> bench name $ whnf f t)

benchByteString :: (ByteString -> ByteString) -> [(Info, ByteString, Text)] -> [Benchmark]
benchByteString f = map (\(Info {name}, b, _) -> bench name $ whnf f b)

main :: IO ()
main = do
  files <- getFiles
  defaultMainWith
    ( defaultConfig
        { reportFile = Just "report.html"
        }
    )
    [ bgroup "GraphQL" $ benchText GQL.parse files,
      bgroup "Morpheus" $ benchByteString Morpheus.parse files
    ]
