{-# LANGUAGE DataKinds #-}
module Examples.UnionExample  where

import Protolude
import GraphQL.API (Field, List, Object, Union)
import GraphQL (Response, interpretAnonymousQuery)
import GraphQL.Resolver (Handler, (:<>)(..), unionValue)

-- Slightly reduced example from the spec
type MiniCat = Object "MiniCat" '[] '[Field "name" Text, Field "meowVolume" Int32]
type MiniDog = Object "MiniDog" '[] '[Field "barkVolume" Int32]

type CatOrDog = Object "Me" '[] '[Field "myPet" (Union "CatOrDog" '[MiniCat, MiniDog])]
type CatOrDogList = Object "CatOrDogList" '[] '[Field "pets" (List (Union "CatOrDog" '[MiniCat, MiniDog]))]

miniCat :: Text -> Handler IO MiniCat
miniCat name = pure (pure name :<> pure 32)

miniDog :: Handler IO MiniDog
miniDog = pure (pure 100)

catOrDog :: Handler IO CatOrDog
catOrDog = pure $ do
  name <- pure "MonadicFelix" -- we can do monadic actions
  unionValue @MiniCat (miniCat name)

catOrDogList :: Handler IO CatOrDogList
catOrDogList = pure $
  pure [ unionValue @MiniCat (miniCat "Felix")
       , unionValue @MiniCat (miniCat "Mini")
       , unionValue @MiniDog miniDog
       ]

-- $setup
-- >>> import Data.Aeson (encode)
-- >>> import GraphQL.Value.ToValue (ToValue(..))

-- | Show usage of a single unionValue
--
-- >>> response <- exampleQuery
-- >>> putStrLn $ encode $ toValue response
-- {"data":{"myPet":{"meowVolume":32,"name":"MonadicFelix"}}}
exampleQuery :: IO Response
exampleQuery = interpretAnonymousQuery @CatOrDog catOrDog "{ myPet { ... on MiniCat { name meowVolume } ... on MiniDog { barkVolume } } }"

-- | 'unionValue' can be used in a list context
--
-- >>> response <- exampleListQuery
-- >>> putStrLn $ encode $ toValue response
-- {"data":{"pets":[{"meowVolume":32,"name":"Felix"},{"meowVolume":32,"name":"Mini"},{"barkVolume":100}]}}
exampleListQuery :: IO Response
exampleListQuery = interpretAnonymousQuery @CatOrDogList catOrDogList  "{ pets { ... on MiniCat { name meowVolume } ... on MiniDog { barkVolume } } }"