/**
   * Performs a POST request to the Singly API that allows specifying the body content of the
   * request. This is used when you need to POST raw content, such as text or images, to the API.
   *
   * <p>Any query parameters passed are appended to the URL versus being passed in the body of the
   * POST request.
   *
   * <p>All network communication is performed in a separate thread. As such it is fine to call this
   * method from the main UI thread.
   *
   * <p>The AsyncApiResponseHandler parameter is an asynchronous callback handler that is used to
   * retrieve the result of the network request to the API. On success the response from the API is
   * returned. On failure a Throwable error object will be returned.
   *
   * <p>If an API call requires an access token it must be added to the queryParams passed into the
   * method.
   *
   * @param context The current android context.
   * @param apiEndpoint The Singly API endpoint to call.
   * @param queryParams Any query parameters to send along with the request.
   * @param body The content to use as the body of the request.
   * @param contentType The MIME content type being sent.
   * @param responseHandler An asynchronous callback handler for the request.
   * @see https://singly.com/docs/api For documentation on Singly api calls.
   * @see SinglyUtils#getAccessToken(Context)
   */
  public void doBodyApiRequest(
      Context context,
      String apiEndpoint,
      Map<String, String> queryParams,
      byte[] body,
      String contentType,
      final AsyncApiResponseHandler responseHandler) {

    // get the http client and add api url
    AsyncHttpClient client = new AsyncHttpClient();
    Map<String, String> params = new LinkedHashMap<String, String>();
    if (queryParams != null) {
      params.putAll(queryParams);
    }
    String postApiCallUrl = SinglyUtils.createSinglyURL(apiEndpoint, params);

    // do an async post request with the raw body content
    client.post(
        context,
        postApiCallUrl,
        new ByteArrayEntity(body),
        contentType,
        new AsyncHttpResponseHandler() {

          @Override
          public void onSuccess(String response) {
            responseHandler.onSuccess(response);
          }

          @Override
          public void onFailure(Throwable error) {
            responseHandler.onFailure(error);
          }
        });
  }
  /**
   * Performs a POST request to the Singly API.
   *
   * <p>All network communication is performed in a separate thread. As such it is fine to call this
   * method from the main UI thread.
   *
   * <p>The AsyncApiResponseHandler parameter is an asynchronous callback handler that is used to
   * retrieve the result of the network request to the API. On success the response from the API is
   * returned. On failure a Throwable error object will be returned.
   *
   * <p>If an API call requires an access token it must be added to the queryParams passed into the
   * method.
   *
   * @param context The current android context.
   * @param apiEndpoint The Singly API endpoint to call.
   * @param queryParams Any query parameters to send along with the request.
   * @param responseHandler An asynchronous callback handler for the request.
   * @see https://singly.com/docs/api For documentation on Singly api calls.
   * @see SinglyUtils#getAccessToken(Context)
   */
  public void doPostApiRequest(
      Context context,
      String apiEndpoint,
      Map<String, String> queryParams,
      final AsyncApiResponseHandler responseHandler) {

    // get the http client and add api url
    AsyncHttpClient client = new AsyncHttpClient();
    Map<String, String> params = new LinkedHashMap<String, String>();
    if (queryParams != null) {
      params.putAll(queryParams);
    }
    String postApiCallUrl = SinglyUtils.createSinglyURL(apiEndpoint);
    RequestParams rparms = params.isEmpty() ? null : new RequestParams(params);

    // do an async post request
    client.post(
        postApiCallUrl,
        rparms,
        new AsyncHttpResponseHandler() {

          @Override
          public void onSuccess(String response) {
            responseHandler.onSuccess(response);
          }

          @Override
          public void onFailure(Throwable error) {
            responseHandler.onFailure(error);
          }
        });
  }