module Database.PostgreSQL.PQTypes.Notification
  ( Channel (..)
  , Notification (..)
  , listen
  , unlisten
  , unlistenAll
  , notify
  ) where

import Data.Text (Text)
import GHC.Stack

import Data.Monoid.Utils
import Database.PostgreSQL.PQTypes.Class
import Database.PostgreSQL.PQTypes.Internal.Notification
import Database.PostgreSQL.PQTypes.SQL.Raw
import Database.PostgreSQL.PQTypes.Utils

-- | Start listening for notifications on a given channel.
listen :: (HasCallStack, MonadDB m) => Channel -> m ()
listen :: forall (m :: * -> *). (HasCallStack, MonadDB m) => Channel -> m ()
listen (Channel RawSQL ()
chan) = RawSQL () -> m ()
forall sql (m :: * -> *).
(HasCallStack, IsSQL sql, MonadDB m) =>
sql -> m ()
runQuery_ (RawSQL () -> m ()) -> RawSQL () -> m ()
forall a b. (a -> b) -> a -> b
$ RawSQL ()
"LISTEN" RawSQL () -> RawSQL () -> RawSQL ()
forall m. (IsString m, Monoid m) => m -> m -> m
<+> RawSQL ()
chan

-- | Stop listening for notifications on a given channel.
unlisten :: (HasCallStack, MonadDB m) => Channel -> m ()
unlisten :: forall (m :: * -> *). (HasCallStack, MonadDB m) => Channel -> m ()
unlisten (Channel RawSQL ()
chan) = RawSQL () -> m ()
forall sql (m :: * -> *).
(HasCallStack, IsSQL sql, MonadDB m) =>
sql -> m ()
runQuery_ (RawSQL () -> m ()) -> RawSQL () -> m ()
forall a b. (a -> b) -> a -> b
$ RawSQL ()
"UNLISTEN" RawSQL () -> RawSQL () -> RawSQL ()
forall m. (IsString m, Monoid m) => m -> m -> m
<+> RawSQL ()
chan

-- | Cancel all listener registrations for the current session.
unlistenAll :: (HasCallStack, MonadDB m) => m ()
unlistenAll :: forall (m :: * -> *). (HasCallStack, MonadDB m) => m ()
unlistenAll = SQL -> m ()
forall (m :: * -> *). (HasCallStack, MonadDB m) => SQL -> m ()
runSQL_ SQL
"UNLISTEN *"

-- | Generate a notification on a given channel.
notify :: (HasCallStack, MonadDB m) => Channel -> Text -> m ()
notify :: forall (m :: * -> *).
(HasCallStack, MonadDB m) =>
Channel -> Text -> m ()
notify (Channel RawSQL ()
chan) Text
payload =
  RawSQL (Text, Text) -> m ()
forall sql (m :: * -> *).
(HasCallStack, IsSQL sql, MonadDB m) =>
sql -> m ()
runQuery_ (RawSQL (Text, Text) -> m ()) -> RawSQL (Text, Text) -> m ()
forall a b. (a -> b) -> a -> b
$
    Text -> (Text, Text) -> RawSQL (Text, Text)
forall row. (Show row, ToRow row) => Text -> row -> RawSQL row
rawSQL Text
"SELECT pg_notify($1, $2)" (RawSQL () -> Text
unRawSQL RawSQL ()
chan, Text
payload)