    {-# LANGUAGE OverloadedStrings #-}

    module Network.MPD.Applicative.Util where

    import           Network.MPD.Commands.Parse
    import           Network.MPD.Commands.Types
    import           Network.MPD.Util

    import           Control.Monad (liftM)

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

    -- Separate the result of an lsinfo\/listallinfo call into directories,
    -- playlists, and songs.
    takeEntries :: [ByteString] -> Either String [LsResult]
    takeEntries :: [ByteString] -> Either String [LsResult]
    takeEntries = ([(ByteString, ByteString)] -> Either String LsResult)
    -> [[(ByteString, ByteString)]] -> Either String [LsResult]
    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 String LsResult
    toEntry ([[(ByteString, ByteString)]] -> Either String [LsResult])
    -> ([ByteString] -> [[(ByteString, ByteString)]])
    -> [ByteString]
    -> Either String [LsResult]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString]
    -> [(ByteString, ByteString)] -> [[(ByteString, ByteString)]]
    splitGroups [ByteString]
    groupHeads ([(ByteString, ByteString)] -> [[(ByteString, ByteString)]])
    -> ([ByteString] -> [(ByteString, ByteString)])
    -> [ByteString]
    -> [[(ByteString, ByteString)]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString] -> [(ByteString, ByteString)]
    toAssocList
        where
            toEntry :: [(ByteString, ByteString)] -> Either String LsResult
    toEntry xs :: [(ByteString, ByteString)]
    xs@((ByteString
    "file",ByteString
    _):[(ByteString, ByteString)]
    _)   = Song -> LsResult
    LsSong (Song -> LsResult) -> Either String Song -> Either String LsResult
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    `liftM` [(ByteString, ByteString)] -> Either String Song
    parseSong [(ByteString, ByteString)]
    xs
            toEntry ((ByteString
    "directory",ByteString
    d):[(ByteString, ByteString)]
    _) = (LsResult -> Either String LsResult
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (LsResult -> Either String LsResult)
    -> (ByteString -> LsResult) -> ByteString -> Either String LsResult
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Path -> LsResult
    LsDirectory (Path -> LsResult)
    -> (ByteString -> Path) -> ByteString -> LsResult
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Path
    Path) ByteString
    d
            toEntry ((ByteString
    "playlist",ByteString
    pl):[(ByteString, ByteString)]
    _) = (LsResult -> Either String LsResult
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (LsResult -> Either String LsResult)
    -> (ByteString -> LsResult) -> ByteString -> Either String LsResult
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PlaylistName -> LsResult
    LsPlaylist (PlaylistName -> LsResult)
    -> (ByteString -> PlaylistName) -> ByteString -> LsResult
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> PlaylistName
    PlaylistName) ByteString
    pl
            toEntry [(ByteString, ByteString)]
    _ = String -> Either String LsResult
    forall a. HasCallStack => String -> a
    error String
    "takeEntries: splitGroups is broken"
            groupHeads :: [ByteString]
    groupHeads = [ByteString
    "file", ByteString
    "directory", ByteString
    "playlist"]

    takeSongs :: [ByteString] -> Either String [Song]
    takeSongs :: [ByteString] -> Either String [Song]
    takeSongs = ([(ByteString, ByteString)] -> Either String Song)
    -> [[(ByteString, ByteString)]] -> Either String [Song]
    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 String Song
    parseSong ([[(ByteString, ByteString)]] -> Either String [Song])
    -> ([ByteString] -> [[(ByteString, ByteString)]])
    -> [ByteString]
    -> Either String [Song]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString]
    -> [(ByteString, ByteString)] -> [[(ByteString, ByteString)]]
    splitGroups [ByteString
    "file"] ([(ByteString, ByteString)] -> [[(ByteString, ByteString)]])
    -> ([ByteString] -> [(ByteString, ByteString)])
    -> [ByteString]
    -> [[(ByteString, ByteString)]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString] -> [(ByteString, ByteString)]
    toAssocList

    -- Run 'toAssocList' and return only the values.
    takeValues :: [ByteString] -> [ByteString]
    takeValues :: [ByteString] -> [ByteString]
    takeValues = ([ByteString], [ByteString]) -> [ByteString]
    forall a b. (a, b) -> b
    snd (([ByteString], [ByteString]) -> [ByteString])
    -> ([ByteString] -> ([ByteString], [ByteString]))
    -> [ByteString]
    -> [ByteString]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [(ByteString, ByteString)] -> ([ByteString], [ByteString])
    forall a b. [(a, b)] -> ([a], [b])
    unzip ([(ByteString, ByteString)] -> ([ByteString], [ByteString]))
    -> ([ByteString] -> [(ByteString, ByteString)])
    -> [ByteString]
    -> ([ByteString], [ByteString])
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString] -> [(ByteString, ByteString)]
    toAssocList

    -- an internal helper function
    decodePair :: (ByteString, ByteString) -> (String, String)
    decodePair :: (ByteString, ByteString) -> (String, String)
    decodePair (ByteString
    x, ByteString
    y) = (ByteString -> String
    UTF8.toString ByteString
    x, ByteString -> String
    UTF8.toString ByteString
    y)