    {-# LANGUAGE OverloadedStrings #-}

    {- |
    Module      : Network.MPD.Applicative.ClientToClient
    Copyright   : (c) Joachim Fasting 2013
    License     : MIT

    Maintainer  : joachifm@fastmail.fm
    Stability   : stable
    Portability : unportable

    Client to client communication.
    -}

    module Network.MPD.Applicative.ClientToClient
        ( -- * Types
          ChannelName
        , MessageText
          -- * Subscribing to channels
        , subscribe
        , unsubscribe
        , channels
          -- * Communicating with other clients
        , readMessages
        , sendMessage
        ) where

    import           Network.MPD.Commands.Arg hiding (Command)
    import           Network.MPD.Applicative.Internal
    import           Network.MPD.Applicative.Util
    import           Network.MPD.Util

    import           Data.ByteString.Char8 (ByteString)
    import qualified Data.ByteString.UTF8 as UTF8

    ------------------------------------------------------------------------

    type ChannelName = String
    type MessageText = String

    ------------------------------------------------------------------------

    subscribe :: ChannelName -> Command ()
    subscribe :: ChannelName -> Command ()
    subscribe ChannelName
    name = Parser () -> [ChannelName] -> Command ()
    forall a. Parser a -> [ChannelName] -> Command a
    Command Parser ()
    emptyResponse [Command
    "subscribe" Command -> ChannelName -> ChannelName
    forall a. MPDArg a => Command -> a -> ChannelName
    <@> ChannelName
    name]

    unsubscribe :: ChannelName -> Command ()
    unsubscribe :: ChannelName -> Command ()
    unsubscribe ChannelName
    name = Parser () -> [ChannelName] -> Command ()
    forall a. Parser a -> [ChannelName] -> Command a
    Command Parser ()
    emptyResponse [Command
    "unsubscribe" Command -> ChannelName -> ChannelName
    forall a. MPDArg a => Command -> a -> ChannelName
    <@> ChannelName
    name]

    channels :: Command [ChannelName]
    channels :: Command [ChannelName]
    channels = Parser [ChannelName] -> [ChannelName] -> Command [ChannelName]
    forall a. Parser a -> [ChannelName] -> Command a
    Command Parser [ChannelName]
    p [ChannelName
    "channels"]
      where
        p :: Parser [ChannelName]
    p = (ByteString -> ChannelName) -> [ByteString] -> [ChannelName]
    forall a b. (a -> b) -> [a] -> [b]
    map ByteString -> ChannelName
    UTF8.toString ([ByteString] -> [ChannelName])
    -> ([ByteString] -> [ByteString]) -> [ByteString] -> [ChannelName]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString] -> [ByteString]
    takeValues ([ByteString] -> [ChannelName])
    -> Parser [ByteString] -> Parser [ChannelName]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Parser [ByteString]
    getResponse

    ------------------------------------------------------------------------

    readMessages :: Command [(ChannelName, MessageText)]
    readMessages :: Command [(ChannelName, ChannelName)]
    readMessages = Parser [(ChannelName, ChannelName)]
    -> [ChannelName] -> Command [(ChannelName, ChannelName)]
    forall a. Parser a -> [ChannelName] -> Command a
    Command (([ByteString] -> Either ChannelName [(ChannelName, ChannelName)])
    -> Parser [(ChannelName, ChannelName)]
    forall a. ([ByteString] -> Either ChannelName a) -> Parser a
    liftParser [ByteString] -> Either ChannelName [(ChannelName, ChannelName)]
    p) [ChannelName
    "readmessages"]
      where
        p :: [ByteString] -> Either ChannelName [(ChannelName, ChannelName)]
    p = ([(ByteString, ByteString)]
     -> Either ChannelName (ChannelName, ChannelName))
    -> [[(ByteString, ByteString)]]
    -> Either ChannelName [(ChannelName, ChannelName)]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM [(ByteString, ByteString)]
    -> Either ChannelName (ChannelName, ChannelName)
    parseMessage ([[(ByteString, ByteString)]]
     -> Either ChannelName [(ChannelName, ChannelName)])
    -> ([ByteString] -> [[(ByteString, ByteString)]])
    -> [ByteString]
    -> Either ChannelName [(ChannelName, ChannelName)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString]
    -> [(ByteString, ByteString)] -> [[(ByteString, ByteString)]]
    splitGroups [ByteString
    "channel"] ([(ByteString, ByteString)] -> [[(ByteString, ByteString)]])
    -> ([ByteString] -> [(ByteString, ByteString)])
    -> [ByteString]
    -> [[(ByteString, ByteString)]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString] -> [(ByteString, ByteString)]
    toAssocList

        parseMessage :: [(ByteString, ByteString)] -> Either String (ChannelName, MessageText)
        parseMessage :: [(ByteString, ByteString)]
    -> Either ChannelName (ChannelName, ChannelName)
    parseMessage [(ByteString
    "channel", ByteString
    ch),(ByteString
    "message", ByteString
    msg)] = (ChannelName, ChannelName)
    -> Either ChannelName (ChannelName, ChannelName)
    forall a b. b -> Either a b
    Right (ByteString -> ChannelName
    UTF8.toString ByteString
    ch, ByteString -> ChannelName
    UTF8.toString ByteString
    msg)
        parseMessage [(ByteString, ByteString)]
    _ = ChannelName -> Either ChannelName (ChannelName, ChannelName)
    forall a b. a -> Either a b
    Left ChannelName
    "Unexpected result from readMessages"

    sendMessage :: ChannelName -> MessageText -> Command ()
    sendMessage :: ChannelName -> ChannelName -> Command ()
    sendMessage ChannelName
    name ChannelName
    text = Parser () -> [ChannelName] -> Command ()
    forall a. Parser a -> [ChannelName] -> Command a
    Command Parser ()
    emptyResponse [Command
    "sendmessage" Command -> Args -> ChannelName
    forall a. MPDArg a => Command -> a -> ChannelName
    <@> ChannelName
    name ChannelName -> ChannelName -> Args
    forall a b. (MPDArg a, MPDArg b) => a -> b -> Args
    <++> ChannelName
    text]