module Conduit.Features.Account.Common.QueryAssociatedUser (queryAssociatedUser) where

import Prelude hiding (on)
import Conduit.Features.Account.Common.QueryUserFollows (queryIfUserFollows)
import Conduit.Features.Account.DB (User)
import Conduit.Features.Account.Types (UserID)
import Database.Esqueleto.Experimental (Entity, PersistEntity, SqlExpr, SqlQuery, Value(..), from, innerJoin, on, table, (:&)(..))

queryAssociatedUser 
  ::  table. (PersistEntity table) 
  => Maybe UserID
  -> (SqlExpr (Entity table) -> SqlExpr (Entity User) -> SqlExpr (Value Bool)) 
  -> SqlQuery (SqlExpr (Entity table) :& SqlExpr (Entity User), SqlExpr (Value Bool))
queryAssociatedUser :: forall table.
PersistEntity table =>
Maybe UserID
-> (SqlExpr (Entity table)
    -> SqlExpr (Entity User) -> SqlExpr (Value Bool))
-> SqlQuery
     (SqlExpr (Entity table) :& SqlExpr (Entity User),
      SqlExpr (Value Bool))
queryAssociatedUser Maybe UserID
userID SqlExpr (Entity table)
-> SqlExpr (Entity User) -> SqlExpr (Value Bool)
relation = do
  joined :: SqlExpr (Entity table) :& SqlExpr (Entity User)
joined@(SqlExpr (Entity table)
_ :& SqlExpr (Entity User)
u) <- From (SqlExpr (Entity table) :& SqlExpr (Entity User))
-> SqlQuery (SqlExpr (Entity table) :& SqlExpr (Entity User))
forall a a'. ToFrom a a' => a -> SqlQuery a'
from (From (SqlExpr (Entity table) :& SqlExpr (Entity User))
 -> SqlQuery (SqlExpr (Entity table) :& SqlExpr (Entity User)))
-> From (SqlExpr (Entity table) :& SqlExpr (Entity User))
-> SqlQuery (SqlExpr (Entity table) :& SqlExpr (Entity User))
forall a b. (a -> b) -> a -> b
$
    forall ent. PersistEntity ent => From (SqlExpr (Entity ent))
table @table
      From (SqlExpr (Entity table))
-> (From (SqlExpr (Entity User)),
    (SqlExpr (Entity table) :& SqlExpr (Entity User))
    -> SqlExpr (Value Bool))
-> From (SqlExpr (Entity table) :& SqlExpr (Entity User))
forall a a' b b' rhs.
(ToFrom a a', ToFrom b b', HasOnClause rhs (a' :& b'),
 rhs ~ (b, (a' :& b') -> SqlExpr (Value Bool))) =>
a -> rhs -> From (a' :& b')
`innerJoin` 
    forall ent. PersistEntity ent => From (SqlExpr (Entity ent))
table @User
      From (SqlExpr (Entity User))
-> ((SqlExpr (Entity table) :& SqlExpr (Entity User))
    -> SqlExpr (Value Bool))
-> (From (SqlExpr (Entity User)),
    (SqlExpr (Entity table) :& SqlExpr (Entity User))
    -> SqlExpr (Value Bool))
forall a b.
ValidOnClause a =>
a -> (b -> SqlExpr (Value Bool)) -> (a, b -> SqlExpr (Value Bool))
`on` \(SqlExpr (Entity table)
a :& SqlExpr (Entity User)
b) -> SqlExpr (Entity table)
-> SqlExpr (Entity User) -> SqlExpr (Value Bool)
relation SqlExpr (Entity table)
a SqlExpr (Entity User)
b

  let follows :: SqlExpr (Value Bool)
follows = SqlExpr (Entity User) -> Maybe UserID -> SqlExpr (Value Bool)
forall a.
ComparableUserEntity a =>
SqlExpr a -> Maybe UserID -> SqlExpr (Value Bool)
queryIfUserFollows SqlExpr (Entity User)
u Maybe UserID
userID

  (SqlExpr (Entity table) :& SqlExpr (Entity User),
 SqlExpr (Value Bool))
-> SqlQuery
     (SqlExpr (Entity table) :& SqlExpr (Entity User),
      SqlExpr (Value Bool))
forall a. a -> SqlQuery a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SqlExpr (Entity table) :& SqlExpr (Entity User)
joined, SqlExpr (Value Bool)
follows)