{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Data.Morpheus.Execution.Document.Encode
( deriveEncode
) where
import Data.Text (unpack)
import Data.Typeable (Typeable)
import Language.Haskell.TH
import Data.Semigroup ((<>))
import Data.Morpheus.Execution.Server.Encode (Encode (..), ObjectResolvers (..))
import Data.Morpheus.Types.GQLType (TRUE)
import Data.Morpheus.Types.Internal.Data (DataField (..), QUERY, SUBSCRIPTION, isSubscription)
import Data.Morpheus.Types.Internal.DataD (ConsD (..), GQLTypeD (..), TypeD (..))
import Data.Morpheus.Types.Internal.Resolver (Resolver, MapGraphQLT (..), Resolving,PureOperation)
import Data.Morpheus.Types.Internal.TH (applyT, destructRecord, instanceHeadMultiT, typeT)
deriveEncode :: GQLTypeD -> Q [Dec]
deriveEncode GQLTypeD {typeKindD, typeD = TypeD {tName, tCons = [ConsD {cFields}]}} =
pure <$> instanceD (cxt constrains) appHead methods
where
subARgs = conT ''SUBSCRIPTION : map (varT . mkName) ["m","e"]
instanceArgs
| isSubscription typeKindD = subARgs
| otherwise = map (varT . mkName) ["o","m","e"]
mainType = applyT (mkName tName) [mainTypeArg]
where
mainTypeArg
| isSubscription typeKindD = applyT ''Resolver subARgs
| otherwise = typeT ''Resolver ["fieldOKind","m","e"]
typeables
| isSubscription typeKindD = [applyT ''MapGraphQLT $ map conT [''QUERY, ''SUBSCRIPTION],applyT ''Resolving [conT ''QUERY, varT $ mkName "m", varT $ mkName "e"]]
| otherwise = [typeT ''PureOperation ["fieldOKind"],typeT ''MapGraphQLT ["fieldOKind","o"] , typeT ''Resolving ["fieldOKind","m","e"] , typeT ''Typeable ["fieldOKind"] , typeT ''Typeable ["o"]]
constrains = typeables <>[typeT ''Monad ["m"], applyT ''Encode (mainType:instanceArgs) , typeT ''Typeable ["m"],typeT ''Typeable ["e"]]
appHead = instanceHeadMultiT ''ObjectResolvers (conT ''TRUE) (mainType: instanceArgs)
methods = [funD 'objectResolvers [clause argsE (normalB body) []]]
where
argsE = [varP (mkName "_"), destructRecord tName varNames]
body = listE $ map decodeVar varNames
decodeVar name = [|(name, encode $(varName))|]
where
varName = varE $ mkName name
varNames = map (unpack . fieldName) cFields
deriveEncode _ = pure []