{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Data.Morpheus.Server.Resolvers
  ( ResolveNamed (..),
    NamedResolverT (..),
    resolve,
    NamedResolvers (..),
    RootResolver (..),
    defaultRootResolver,
    ResolverO,
    ComposedResolver,
    publish,
    constRes,
    ResolverQ,
    ResolverM,
    ResolverS,
    useBatched,
    ignoreBatching,
  )
where

import Data.Morpheus.App.Internal.Resolving (PushEvents (pushEvents), Resolver, WithOperation)
import Data.Morpheus.Server.NamedResolvers
  ( NamedResolverT (..),
    ResolveNamed (..),
    ignoreBatching,
    resolve,
    useBatched,
  )
import Data.Morpheus.Server.Types.Types
  ( Undefined (..),
  )
import Data.Morpheus.Types.Internal.AST
import Relude hiding (Undefined)

data
  NamedResolvers
    (m :: Type -> Type)
    event
    (qu :: (Type -> Type) -> Type)
    (mu :: (Type -> Type) -> Type)
    (su :: (Type -> Type) -> Type)
  = ( ResolveNamed
        (Resolver QUERY event m)
        (qu (NamedResolverT (Resolver QUERY event m)))
    ) =>
    NamedResolvers

-- | GraphQL Root resolver, also the interpreter generates a GQL schema from it.
--  'queryResolver' is required, 'mutationResolver' and 'subscriptionResolver' are optional,
--  if your schema does not supports __mutation__ or __subscription__ , you can use __()__ for it.
data
  RootResolver
    (m :: Type -> Type)
    event
    (query :: (Type -> Type) -> Type)
    (mutation :: (Type -> Type) -> Type)
    (subscription :: (Type -> Type) -> Type) = RootResolver
  { forall (m :: * -> *) event (query :: (* -> *) -> *)
       (mutation :: (* -> *) -> *) (subscription :: (* -> *) -> *).
RootResolver m event query mutation subscription
-> query (Resolver QUERY event m)
queryResolver :: query (Resolver QUERY event m),
    forall (m :: * -> *) event (query :: (* -> *) -> *)
       (mutation :: (* -> *) -> *) (subscription :: (* -> *) -> *).
RootResolver m event query mutation subscription
-> mutation (Resolver MUTATION event m)
mutationResolver :: mutation (Resolver MUTATION event m),
    forall (m :: * -> *) event (query :: (* -> *) -> *)
       (mutation :: (* -> *) -> *) (subscription :: (* -> *) -> *).
RootResolver m event query mutation subscription
-> subscription (Resolver SUBSCRIPTION event m)
subscriptionResolver :: subscription (Resolver SUBSCRIPTION event m)
  }

defaultRootResolver :: RootResolver m event Undefined Undefined Undefined
defaultRootResolver :: forall (m :: * -> *) event.
RootResolver m event Undefined Undefined Undefined
defaultRootResolver =
  RootResolver
    { queryResolver :: Undefined (Resolver QUERY event m)
queryResolver = forall (m :: * -> *). Bool -> Undefined m
Undefined Bool
False,
      mutationResolver :: Undefined (Resolver MUTATION event m)
mutationResolver = forall (m :: * -> *). Bool -> Undefined m
Undefined Bool
False,
      subscriptionResolver :: Undefined (Resolver SUBSCRIPTION event m)
subscriptionResolver = forall (m :: * -> *). Bool -> Undefined m
Undefined Bool
False
    }

class FlexibleResolver (f :: Type -> Type) (a :: k) where
  type Flexible (m :: Type -> Type) a :: Type
  type Composed (m :: Type -> Type) f a :: Type

instance FlexibleResolver f (a :: Type) where
  type Flexible m a = m a
  type Composed m f a = m (f a)

instance FlexibleResolver f (a :: (Type -> Type) -> Type) where
  type Flexible m a = m (a m)
  type Composed m f a = m (f (a m))

type ComposedResolver o e m f a = Composed (Resolver o e m) f a

type ResolverO o e m a = Flexible (Resolver o e m) a

type ResolverQ e m a = Flexible (Resolver QUERY e m) a

type ResolverM e m a = Flexible (Resolver MUTATION e m) a

type ResolverS e m a = Flexible (Resolver SUBSCRIPTION e m) a

publish :: Monad m => [e] -> Resolver MUTATION e m ()
publish :: forall (m :: * -> *) e. Monad m => [e] -> Resolver MUTATION e m ()
publish = forall e (m :: * -> *). PushEvents e m => [e] -> m ()
pushEvents

constRes :: (WithOperation o, Monad m) => b -> a -> Resolver o e m b
constRes :: forall (o :: OperationType) (m :: * -> *) b a e.
(WithOperation o, Monad m) =>
b -> a -> Resolver o e m b
constRes = forall a b. a -> b -> a
const forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a. Applicative f => a -> f a
pure