module Mongrel2.Response
       ( Response
       , mkResponse
       ) where

import Blaze.ByteString.Builder (Builder, toByteString, fromByteString)
import Blaze.Text.Int (integral)
import Data.ByteString (ByteString)
import Data.ByteString.Char8 ()
import Data.List (intersperse)
import Data.Monoid
import Mongrel2.Types (ClientID, UUID)
import qualified Data.ByteString as S

-- | Raw response type.
type Response = ByteString

-- | Build a single space.
buildSpace :: Builder
buildSpace = fromByteString " "

-- | Build a UUID.
buildUUID :: UUID -> Builder
buildUUID = fromByteString

-- | Build a netstring from a builder.
buildNetstring :: Builder -> Builder
buildNetstring b =
  -- TODO: Is it possible to find the length without "forcing" the Builder?
  mconcat [ integral $ S.length s
          , fromByteString ":"
          , fromByteString s
          ]
  where
    s = toByteString b

-- | Build client ID list.
buildClientIDList :: [ClientID] -> Builder
buildClientIDList cids =
  mconcat $ intersperse buildSpace $ map integral cids

-- | Build a response from a server UUID, a list of
-- client IDs and a response body builder.
mkResponse :: UUID -> [ClientID] -> Builder -> Response
mkResponse uuid clientIDs bodyBuilder =
  toByteString $ mconcat [ buildUUID uuid
                         , buildSpace
                         , buildNetstring $ buildClientIDList clientIDs
                         , fromByteString ", "
                         , bodyBuilder ]