content: {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE DuplicateRecordFields #-}
  {-# LANGUAGE FlexibleContexts #-}
  {-# LANGUAGE FlexibleInstances #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE TypeFamilies #-}
  {-# OPTIONS_GHC -Wno-orphans #-}
  
  module Feature.NamedResolvers.RealmsApp
    ( realmsApp,
      Deity,
      Realm,
    )
  where
  
  import Data.Morpheus.Server
    ( deriveApp,
    )
  import Data.Morpheus.Server.Resolvers
    ( NamedResolverT,
      NamedResolvers (..),
      ResolveNamed (..),
      ignoreBatching,
      resolve,
    )
  import Data.Morpheus.Server.Types
    ( App,
      Arg (..),
      ID,
      Undefined,
    )
  import Feature.NamedResolvers.DB
    ( allDeities,
      allRealms,
      getOwner,
      getPlace,
      getRealmName,
    )
  import Feature.NamedResolvers.Realms
  
  getRealm :: (Monad m) => ID -> m (Maybe (Realm (NamedResolverT m)))
  getRealm uid
    | uid `elem` allRealms =
        pure
          $ Just
            Realm
              { name = resolve (getRealmName uid),
                owner = resolve (getOwner uid),
                description = resolve (pure uid)
              }
  getRealm _ = pure Nothing
  
  instance ResolveNamed m (Realm (NamedResolverT m)) where
    type Dep (Realm (NamedResolverT m)) = ID
  
    resolveBatched = traverse getRealm
  
  instance ResolveNamed m (Deity (NamedResolverT m)) where
    type Dep (Deity (NamedResolverT m)) = ID
    resolveBatched = traverse getDeity
  
  getDeity :: (Monad m) => ID -> m (Maybe (Deity (NamedResolverT m)))
  getDeity arg
    | arg `elem` allDeities = pure $ Just Deity {realm = resolve (getPlace arg)}
    | otherwise = pure Nothing
  
  instance ResolveNamed m (Query (NamedResolverT m)) where
    type Dep (Query (NamedResolverT m)) = ()
    resolveBatched =
      ignoreBatching
        $ const
        $ pure
          Query
            { realm = \(Arg arg) -> resolve (pure arg),
              realms = resolve (pure allRealms)
            }
  
  realmsApp :: App () IO
  realmsApp =
    deriveApp
      (NamedResolvers :: NamedResolvers IO () Query Undefined Undefined)
  