{-# LANGUAGE ConstrainedClassMethods #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Data.Morpheus.App.Internal.Resolving.MonadResolver
  ( MonadResolver (..),
    MonadIOResolver,
    SubscriptionField (..),
    ResolverContext (..),
    withArguments,
    getArgument,
  )
where

import Control.Monad.Except (MonadError)
import Data.Morpheus.App.Internal.Resolving.Event
  ( EventHandler (..),
    ResponseEvent,
  )
import Data.Morpheus.App.Internal.Resolving.ResolverState
  ( ResolverContext (..),
    ResolverState,
  )
import Data.Morpheus.Internal.Ext (ResultT)
import Data.Morpheus.Internal.Utils (selectOr)
import Data.Morpheus.Types.Internal.AST
  ( Argument (..),
    Arguments,
    FieldName,
    GQLError,
    MUTATION,
    OperationType,
    SUBSCRIPTION,
    Selection,
    VALID,
    ValidValue,
    Value (..),
  )
import Relude

class (MonadResolver m, MonadIO m) => MonadIOResolver (m :: Type -> Type)

class
  ( Monad m,
    MonadReader ResolverContext m,
    MonadFail m,
    MonadError GQLError m,
    Monad (MonadParam m)
  ) =>
  MonadResolver (m :: Type -> Type)
  where
  type MonadOperation m :: OperationType
  type MonadEvent m :: Type
  type MonadQuery m :: (Type -> Type)
  type MonadMutation m :: (Type -> Type)
  type MonadSubscription m :: (Type -> Type)
  type MonadParam m :: (Type -> Type)
  liftState :: ResolverState a -> m a
  getArguments :: m (Arguments VALID)
  subscribe :: (MonadOperation m ~ SUBSCRIPTION) => Channel (MonadEvent m) -> MonadQuery m (MonadEvent m -> m a) -> SubscriptionField (m a)
  publish :: (MonadOperation m ~ MUTATION) => [MonadEvent m] -> m ()
  runResolver ::
    Maybe (Selection VALID -> ResolverState (Channel (MonadEvent m))) ->
    m ValidValue ->
    ResolverContext ->
    ResponseStream (MonadEvent m) (MonadParam m) ValidValue

data SubscriptionField (a :: Type) where
  SubscriptionField ::
    { forall a.
SubscriptionField a
-> forall (m :: * -> *) v.
   (a ~ m v, MonadResolver m, MonadOperation m ~ SUBSCRIPTION) =>
   Channel (MonadEvent m)
channel :: forall m v. (a ~ m v, MonadResolver m, MonadOperation m ~ SUBSCRIPTION) => Channel (MonadEvent m),
      forall a. SubscriptionField a -> a
unSubscribe :: a
    } ->
    SubscriptionField a

withArguments :: (MonadResolver m) => (Arguments VALID -> m a) -> m a
withArguments :: forall (m :: * -> *) a.
MonadResolver m =>
(Arguments VALID -> m a) -> m a
withArguments = (forall (m :: * -> *). MonadResolver m => m (Arguments VALID)
getArguments forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=)

getArgument :: (MonadResolver m) => FieldName -> m (Value VALID)
getArgument :: forall (m :: * -> *).
MonadResolver m =>
FieldName -> m (Value VALID)
getArgument FieldName
name = forall k (c :: * -> *) d a.
IsMap k c =>
d -> (a -> d) -> k -> c a -> d
selectOr forall (stage :: Stage). Value stage
Null forall (valid :: Stage). Argument valid -> Value valid
argumentValue FieldName
name forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). MonadResolver m => m (Arguments VALID)
getArguments

type ResponseStream event (m :: Type -> Type) = ResultT (ResponseEvent event m) m