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

import Data.Text (Text)

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 :: MonadDB m => Channel -> m ()
listen :: forall (m :: * -> *). MonadDB m => Channel -> m ()
listen (Channel RawSQL ()
chan) = forall sql (m :: * -> *). (IsSQL sql, MonadDB m) => sql -> m ()
runQuery_ forall a b. (a -> b) -> a -> b
$ RawSQL ()
"LISTEN" forall m. (IsString m, Monoid m) => m -> m -> m
<+> RawSQL ()
chan

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

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

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