-- TODO - return '400 bad request' if we can't convert it
-- | Convert a WAI 'W.Request' to a Happstack 'H.Request'.
convertRequest :: W.Request -- ^ WAI request
               -> ResourceT IO H.Request
convertRequest wReq = do
  bodyInputRef <- liftIO newEmptyMVar
  bodyLbs <- BL.fromChunks <$> C.lazyConsume (W.requestBody wReq)
  bodyRef <- liftIO $ newMVar $ H.Body bodyLbs

  return $
    H.Request
#if MIN_VERSION_happstack_server(6,5,0)
     (W.isSecure wReq)
#endif
     (convertMethod $ W.requestMethod wReq)
     (convertPath $ W.pathInfo wReq)
     rawPath -- includes leading slash, does not include query
     rawQuery -- includes leading questionmark
     parsedQuery
     bodyInputRef
     cookies
     httpVersion
     headers
     bodyRef
     (B8.unpack (W.serverName wReq), W.serverPort wReq)

  where
    headers :: H.Headers -- Map ByteString HeaderPair
    headers =
        let assocs = flip map (W.requestHeaders wReq) $ \(ciName, val) ->
                     (CI.original ciName, val)
        in mkHeadersBs assocs

    httpVersion :: H.HttpVersion
    httpVersion =
        case W.httpVersion wReq of
          W.HttpVersion major minor ->
              H.HttpVersion major minor

    cookies :: [(String, H.Cookie)]
    cookies =
        let cookieHeaders =
                filter (\x -> fst x == "Cookie") $ W.requestHeaders wReq
            rawCookies =
                map snd cookieHeaders
            foundCookies =
                concat $ mapMaybe H.getCookies rawCookies
        in map (\c -> (H.cookieName c, c)) foundCookies

    parsedQuery :: [(String,H.Input)]
    parsedQuery =
        case rawQuery of
          '?':xs -> H.formDecode xs
          xs     -> H.formDecode xs

    rawQuery :: String
    rawQuery = B8.unpack $ W.rawQueryString wReq

    rawPath :: String
    rawPath =
        B8.unpack . fst $ B.breakByte 63 (W.rawPathInfo wReq) -- 63 == '?'
convertRequest :: W.Request -- ^ WAI request
               -> ResourceT IO H.Request
convertRequest wReq = do
  bodyInputRef <- liftIO newEmptyMVar
  bodyLbs <- BL.fromChunks <$> C.lazyConsume (W.requestBody wReq)
  bodyRef <- liftIO $ newMVar $ H.Body bodyLbs

  return $
    H.Request
#if MIN_VERSION_happstack_server(6,5,0)
     (W.isSecure wReq)
#endif
     (convertMethod $ W.requestMethod wReq)
     (convertPath $ W.pathInfo wReq)
     rawPath -- includes leading slash, does not include query
     rawQuery -- includes leading questionmark
     parsedQuery
     bodyInputRef
     cookies
     httpVersion
     headers
     bodyRef
     (B8.unpack (W.serverName wReq), W.serverPort wReq)

  where
    headers :: H.Headers -- Map ByteString HeaderPair
    headers =
        let assocs = flip map (W.requestHeaders wReq) $ \(ciName, val) ->
                     (CI.original ciName, val)
        in mkHeadersBs assocs

    httpVersion :: H.HttpVersion
    httpVersion =
        case W.httpVersion wReq of
          W.HttpVersion major minor ->
              H.HttpVersion major minor

    cookies :: [(String, H.Cookie)]
    cookies =
        let cookieHeaders =
                filter (\x -> fst x == "Cookie") $ W.requestHeaders wReq
            rawCookies =
                map snd cookieHeaders
            foundCookies =
                concat $ mapMaybe H.getCookies rawCookies
        in map (\c -> (H.cookieName c, c)) foundCookies

    parsedQuery :: [(String,H.Input)]
    parsedQuery =
        case rawQuery of
          '?':xs -> H.formDecode xs
          xs     -> H.formDecode xs

    rawQuery :: String
    rawQuery = B8.unpack $ W.rawQueryString wReq

    rawPath :: String
    rawPath =
        B8.unpack . fst $ B.breakByte 63 (W.rawPathInfo wReq) -- 63 == '?'
convertRequest wReq = do
  bodyInputRef <- liftIO newEmptyMVar
  bodyLbs <- BL.fromChunks <$> C.lazyConsume (W.requestBody wReq)
  bodyRef <- liftIO $ newMVar $ H.Body bodyLbs

  return $
    H.Request
#if MIN_VERSION_happstack_server(6,5,0)
     (W.isSecure wReq)
#endif
     (convertMethod $ W.requestMethod wReq)
     (convertPath $ W.pathInfo wReq)
     rawPath -- includes leading slash, does not include query
     rawQuery -- includes leading questionmark
     parsedQuery
     bodyInputRef
     cookies
     httpVersion
     headers
     bodyRef
     (B8.unpack (W.serverName wReq), W.serverPort wReq)

  where
    headers :: H.Headers -- Map ByteString HeaderPair
    headers =
        let assocs = flip map (W.requestHeaders wReq) $ \(ciName, val) ->
                     (CI.original ciName, val)
        in mkHeadersBs assocs

    httpVersion :: H.HttpVersion
    httpVersion =
        case W.httpVersion wReq of
          W.HttpVersion major minor ->
              H.HttpVersion major minor

    cookies :: [(String, H.Cookie)]
    cookies =
        let cookieHeaders =
                filter (\x -> fst x == "Cookie") $ W.requestHeaders wReq
            rawCookies =
                map snd cookieHeaders
            foundCookies =
                concat $ mapMaybe H.getCookies rawCookies
        in map (\c -> (H.cookieName c, c)) foundCookies

    parsedQuery :: [(String,H.Input)]
    parsedQuery =
        case rawQuery of
          '?':xs -> H.formDecode xs
          xs     -> H.formDecode xs

    rawQuery :: String
    rawQuery = B8.unpack $ W.rawQueryString wReq

    rawPath :: String
    rawPath =
        B8.unpack . fst $ B.breakByte 63 (W.rawPathInfo wReq) -- 63 == '?'