{-# 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,
    constRes,
    ResolverQ,
    ResolverM,
    ResolverS,
    useBatched,
    ignoreBatching,
    Flexible,
    Composed,
  )
where

import Data.Morpheus.App.Internal.Resolving
  ( MonadResolver (..),
    Resolver,
  )
import Data.Morpheus.Server.Types.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 = ResolverO QUERY e m a

type ResolverM e m a = ResolverO MUTATION e m a

type ResolverS e m a = ResolverO SUBSCRIPTION e m a

constRes :: (MonadResolver m) => b -> a -> m b
constRes :: forall (m :: * -> *) b a. MonadResolver m => b -> a -> 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