     end
   end
 
-  defmodule Erl do
-    @moduledoc false
-    # Wraps Erlang's `httpc` (http://erlang.org/doc/man/httpc.html)
-    # Works in synchronous mode.
-
-    @type headers_t :: [{String.t, String.t}]
-    @type res_t :: {:ok, {status_code :: integer, headers_t, body :: String.t}} | {:error, reason :: term}
-
-    @spec request(atom, String.t, headers_t, String.t | nil, String.t | nil, Keyword.t, Keyword.t) :: res_t
-    def request(method, url_with_param, headers, content_type, body, http_options, options) do
-      req = httpc_req(url_with_param, headers, content_type, body)
-      case :httpc.request(method, req, to_charlist_kvs(http_options), force_sync_options(options)) do
-        {:ok, {{_http_ver, status, _reason}, resp_headers, resp_body}} ->
-          {:ok, {status, from_charlist_kvs(resp_headers), resp_body}}
-        {:error, _} = e ->
-          e
-      end
-    end
-
-    defp binary_to_charlist(binary) when is_binary(binary), do: to_charlist(binary)
-    defp binary_to_charlist(other), do: other
-
-    defp to_charlist_kvs(kvs) do
-      Enum.map(kvs, fn {key, val} -> {binary_to_charlist(key), binary_to_charlist(val)} end)
-    end
-
-    defp httpc_req(url_with_param, headers, nil, nil) do
-      {binary_to_charlist(url_with_param), to_charlist_kvs(headers)}
-    end
-    defp httpc_req(url_with_param, headers, content_type, body) do
-      {binary_to_charlist(url_with_param), to_charlist_kvs(headers), binary_to_charlist(content_type), body}
-    end
-
-    defp force_sync_options(options) do
-      options
-      |> Keyword.merge([
-        sync: true,
-        body_format: :binary,
-        full_result: true,
-      ])
-      |> to_charlist_kvs()
-    end
-
-    defp from_charlist_kvs(kvs) do
-      Enum.map(kvs, fn {key, val} -> {List.to_string(key), List.to_string(val)} end)
-    end
-  end
-
   @type method_t  :: :get | :post | :put | :delete
   @type headers_t :: [{String.t, String.t}]
   @type options_t :: list

    Application.get_env(:hipchat_elixir, :serializer, Poison)
  end

  defp convert_resp_headers(resp_headers) do
    Map.new(resp_headers, fn {key, value} ->
      {String.downcase(key), value}
    end)
  end
end

  @doc """
  Send HTTP request with the given parameters.

  `options` accepts any options available in `:httpc.request/4`. Additionally,

  - `:http_options` for `http_options` in `:httpc.request/4`
  - `:params` option can take query params as `Hipchat.Client.query_params_t`.
  """
  @spec request(method_t, String.t, term, headers_t, options_t) :: res_t
  def request(method, url, body, headers, options \\ []) do
    url1          = url_with_params(url, options)
    {body1, type} = serialize_body(body)
    httpc_req     = httpc_req(url1, headers, type, body1)
    request_dump  = %{method: method, httpc_req: httpc_req}
    case :httpc.request(method, httpc_req, Keyword.get(options, :http_options, []), force_sync_options(options)) do
      {:ok, {{_http_ver, status, _reason}, resp_headers, resp_body}} ->
        Response.new(status, charlist_kvs_to_map(resp_headers), resp_body, request_dump)
      {:error, _} = error_tuple ->
        error_tuple
    end
  end

  defp url_with_params(url, options) do
    case options[:params] do
      [_ | _] = params -> URI.encode(url) <> "?" <> URI.encode_query(params)
      _empty_or_nil    -> URI.encode(url)
    end
  end

  defp serialize_body("") do
    {nil, nil}
  end
  defp serialize_body(body) do
    case serializer() do
      Poison ->
        {Poison.encode!(body), 'application/json'}
      :form ->
        {URI.encode_query(body), 'application/x-www-form-urlencoded'}
    end
  end

