{-# LANGUAGE OverloadedStrings #-}

{-

This file is part of the Haskell package playlists. It is subject to
the license terms in the LICENSE file found in the top-level directory
of this distribution and at git://pmade.com/playlists/LICENSE. No part
of playlists package, including this file, may be copied, modified,
propagated, or distributed except according to the terms contained in
the LICENSE file.

-}

--------------------------------------------------------------------------------
module Text.Playlist.PLS.Writer
       ( writePlaylist
       , writeTrack
       ) where

--------------------------------------------------------------------------------
import Data.ByteString.Lazy.Builder (Builder)
import qualified Data.ByteString.Lazy.Builder as B
import Data.Text.Encoding (encodeUtf8)
import Text.Playlist.Types

--------------------------------------------------------------------------------
writePlaylist :: Playlist -> Builder
writePlaylist :: Playlist -> Builder
writePlaylist Playlist
x =
  ByteString -> Builder
B.byteString ByteString
"[playlist]\n"                  Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
  [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ((Track -> Int -> Builder) -> Playlist -> [Int] -> [Builder]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (((Track, Int) -> Builder) -> Track -> Int -> Builder
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (Track, Int) -> Builder
writeTrack) Playlist
x [Int
1..]) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
  ByteString -> Builder
B.byteString ByteString
"NumberOfEntries="              Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
  String -> Builder
B.stringUtf8 (Int -> String
forall a. Show a => a -> String
show (Int -> String) -> (Playlist -> Int) -> Playlist -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Playlist -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Playlist -> String) -> Playlist -> String
forall a b. (a -> b) -> a -> b
$ Playlist
x)             Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
  ByteString -> Builder
B.byteString ByteString
"\nVersion=2\n"

--------------------------------------------------------------------------------
writeTrack :: (Track, Int) -> Builder
writeTrack :: (Track, Int) -> Builder
writeTrack (Track, Int)
x = (Track, Int) -> Builder
writeFileN (Track, Int)
x Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Track, Int) -> Builder
writeTitle (Track, Int)
x Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Track, Int) -> Builder
writeLength (Track, Int)
x

--------------------------------------------------------------------------------
writeFileN :: (Track, Int) -> Builder
writeFileN :: (Track, Int) -> Builder
writeFileN (Track
x, Int
n) =
  ByteString -> Builder
B.byteString ByteString
"File"                      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
  String -> Builder
B.stringUtf8 (Int -> String
forall a. Show a => a -> String
show Int
n)                    Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
  Char -> Builder
B.charUtf8 Char
'='                           Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
  ByteString -> Builder
B.byteString (Text -> ByteString
encodeUtf8 (Text -> ByteString) -> (Track -> Text) -> Track -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Track -> Text
trackURL (Track -> ByteString) -> Track -> ByteString
forall a b. (a -> b) -> a -> b
$ Track
x) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
  Char -> Builder
B.charUtf8 Char
'\n'

--------------------------------------------------------------------------------
writeTitle :: (Track, Int) -> Builder
writeTitle :: (Track, Int) -> Builder
writeTitle (Track
x, Int
n) =
  case Track -> Maybe Text
trackTitle Track
x of
    Maybe Text
Nothing -> Builder
forall a. Monoid a => a
mempty
    Just Text
y  -> ByteString -> Builder
B.byteString ByteString
"Title"        Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
               String -> Builder
B.stringUtf8 (Int -> String
forall a. Show a => a -> String
show Int
n)       Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
               Char -> Builder
B.charUtf8 Char
'='              Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
               ByteString -> Builder
B.byteString (Text -> ByteString
encodeUtf8 Text
y) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
               Char -> Builder
B.charUtf8 Char
'\n'

--------------------------------------------------------------------------------
writeLength :: (Track, Int) -> Builder
writeLength :: (Track, Int) -> Builder
writeLength (Track
x, Int
n) =
  case Track -> Maybe Float
trackDuration Track
x of
    Maybe Float
Nothing -> Builder
forall a. Monoid a => a
mempty
    Just Float
l  -> ByteString -> Builder
B.byteString ByteString
"Length" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
               String -> Builder
B.stringUtf8 (Int -> String
forall a. Show a => a -> String
show Int
n) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
               Char -> Builder
B.charUtf8 Char
'='        Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
               String -> Builder
B.stringUtf8 (Float -> String
forall a. Show a => a -> String
show Float
l) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
               Char -> Builder
B.charUtf8 Char
'\n'