{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}

module Data.Morpheus.Server.Deriving.Utils.Use
  ( UseDeriving (..),
    UseGQLType (..),
    UseValue (..),
    UseResolver (..),
    UseNamedResolver (..),
  )
where

import Data.Morpheus.App.Internal.Resolving (NamedResolver (..), ResolverState, ResolverValue)
import Data.Morpheus.Internal.Ext (GQLResult)
import Data.Morpheus.Server.Deriving.Utils.GScan (ScanRef)
import Data.Morpheus.Server.Deriving.Utils.Kinded (CatType)
import Data.Morpheus.Server.Types.Directives
  ( GDirectiveUsages (..),
  )
import Data.Morpheus.Server.Types.Internal
import Data.Morpheus.Server.Types.SchemaT
  ( SchemaT,
  )
import Data.Morpheus.Server.Types.TypeName
  ( TypeFingerprint,
  )
import Data.Morpheus.Types.Internal.AST
  ( ArgumentsDefinition,
    CONST,
    TypeDefinition (..),
    TypeName,
    ValidValue,
    Value,
  )

data UseGQLType gql = UseGQLType
  { forall (gql :: * -> Constraint).
UseGQLType gql
-> forall (c :: TypeCategory) a.
   gql a =>
   CatType c a -> TypeFingerprint
useFingerprint :: forall c a. gql a => CatType c a -> TypeFingerprint,
    forall (gql :: * -> Constraint).
UseGQLType gql
-> forall (c :: TypeCategory) a. gql a => CatType c a -> TypeName
useTypename :: forall c a. gql a => CatType c a -> TypeName,
    forall (gql :: * -> Constraint).
UseGQLType gql
-> forall (c :: TypeCategory) a. gql a => CatType c a -> TypeData
useTypeData :: forall c a. gql a => CatType c a -> TypeData,
    forall (gql :: * -> Constraint).
UseGQLType gql
-> forall (c :: TypeCategory) a.
   gql a =>
   CatType c a -> SchemaT c (TypeDefinition c CONST)
useDeriveType :: forall c a. gql a => CatType c a -> SchemaT c (TypeDefinition c CONST),
    forall (gql :: * -> Constraint).
UseGQLType gql
-> forall (c :: TypeCategory) a.
   gql a =>
   CatType c a -> SchemaT c (Maybe (ArgumentsDefinition CONST))
useDeriveFieldArguments :: forall c a. gql a => CatType c a -> SchemaT c (Maybe (ArgumentsDefinition CONST))
  }

data UseValue val = UseValue
  { forall (val :: * -> Constraint).
UseValue val -> forall a. val a => a -> GQLResult (Value CONST)
useEncodeValue :: forall a. val a => a -> GQLResult (Value CONST),
    forall (val :: * -> Constraint).
UseValue val -> forall a. val a => ValidValue -> ResolverState a
useDecodeValue :: forall a. val a => ValidValue -> ResolverState a
  }

data UseResolver res gql val = UseResolver
  { forall (res :: (* -> *) -> * -> Constraint)
       (gql :: * -> Constraint) (val :: * -> Constraint).
UseResolver res gql val
-> forall a (m :: * -> *). res m a => a -> m (ResolverValue m)
useEncodeResolver :: forall a m. res m a => a -> m (ResolverValue m),
    forall (res :: (* -> *) -> * -> Constraint)
       (gql :: * -> Constraint) (val :: * -> Constraint).
UseResolver res gql val -> UseDeriving gql val
resDrv :: UseDeriving gql val
  }

data UseDeriving gql val = UseDeriving
  { forall (gql :: * -> Constraint) (val :: * -> Constraint).
UseDeriving gql val
-> forall (f :: * -> *) a. gql a => f a -> GDirectiveUsages gql val
__directives :: forall f a. gql a => f a -> GDirectiveUsages gql val,
    forall (gql :: * -> Constraint) (val :: * -> Constraint).
UseDeriving gql val -> UseValue val
dirArgs :: UseValue val,
    forall (gql :: * -> Constraint) (val :: * -> Constraint).
UseDeriving gql val -> UseGQLType gql
dirGQL :: UseGQLType gql
  }

data UseNamedResolver named fun gql val = UseNamedResolver
  { forall (named :: (* -> *) -> * -> Constraint)
       (fun :: (* -> *) -> * -> Constraint) (gql :: * -> Constraint)
       (val :: * -> Constraint).
UseNamedResolver named fun gql val
-> forall a (m :: * -> *). fun m a => a -> m (ResolverValue m)
useNamedFieldResolver :: forall a m. fun m a => a -> m (ResolverValue m),
    forall (named :: (* -> *) -> * -> Constraint)
       (fun :: (* -> *) -> * -> Constraint) (gql :: * -> Constraint)
       (val :: * -> Constraint).
UseNamedResolver named fun gql val
-> forall (f :: * -> *) a (m :: * -> *).
   named m a =>
   f a -> [NamedResolver m]
useDeriveNamedResolvers :: forall f a m. named m a => f a -> [NamedResolver m],
    forall (named :: (* -> *) -> * -> Constraint)
       (fun :: (* -> *) -> * -> Constraint) (gql :: * -> Constraint)
       (val :: * -> Constraint).
UseNamedResolver named fun gql val
-> forall (f :: * -> *) a (m :: * -> *).
   named m a =>
   f a -> [ScanRef (named m)]
useDeriveNamedRefs :: forall f a m. named m a => f a -> [ScanRef (named m)],
    forall (named :: (* -> *) -> * -> Constraint)
       (fun :: (* -> *) -> * -> Constraint) (gql :: * -> Constraint)
       (val :: * -> Constraint).
UseNamedResolver named fun gql val -> UseDeriving gql val
namedDrv :: UseDeriving gql val
  }