/**
   * Synchronous call for logging in
   *
   * @param httpBody
   * @return The data from the server as a string, in almost all cases JSON
   * @throws MalformedURLException
   * @throws IOException
   * @throws JSONException
   */
  public static String getLoginResponse(Bundle httpBody) throws MalformedURLException, IOException {
    String response = "";
    URL url = new URL(WebServiceAuthProvider.tokenURL());
    HttpsURLConnection connection = createSecureConnection(url);
    String authString = "mobile_android:secret";
    String authValue = "Basic " + Base64.encodeToString(authString.getBytes(), Base64.NO_WRAP);

    connection.setRequestMethod("POST");
    connection.setRequestProperty("Authorization", authValue);
    connection.setDoOutput(true);
    connection.setDoInput(true);
    connection.connect();

    OutputStream os = new BufferedOutputStream(connection.getOutputStream());
    os.write(encodePostBody(httpBody).getBytes());
    os.flush();
    try {
      LoggingUtils.d(LOG_TAG, connection.toString());
      response = readFromStream(connection.getInputStream());
    } catch (MalformedURLException e) {
      LoggingUtils.e(
          LOG_TAG,
          "Error reading stream \""
              + connection.getInputStream()
              + "\". "
              + e.getLocalizedMessage(),
          null);
    } catch (IOException e) {
      response = readFromStream(connection.getErrorStream());
    } finally {
      connection.disconnect();
    }

    return response;
  }
  /**
   * Synchronous call for logging out
   *
   * @return The data from the server as a string, in almost all cases JSON
   * @throws MalformedURLException
   * @throws IOException
   * @throws JSONException
   */
  public static String getLogoutResponse(Context context)
      throws MalformedURLException, IOException, JSONException {
    // Refresh if necessary
    if (WebServiceAuthProvider.tokenExpiredHint(context)) {
      WebServiceAuthProvider.refreshAccessToken(context);
    }

    boolean refreshLimitReached = false;
    int refreshed = 0;

    String response = "";
    while (!refreshLimitReached) {
      // If we have refreshed max number of times, we will not do so again
      if (refreshed == 1) {
        refreshLimitReached = true;
      }

      URL url = new URL(urlForLogout(context));
      HttpsURLConnection connection = createSecureConnection(url);
      String authValue = "Bearer " + SDKSettings.getSharedPreferenceString(context, "access_token");

      connection.setRequestMethod("POST");
      connection.setRequestProperty("Authorization", authValue);
      connection.setDoOutput(true);
      connection.setDoInput(true);
      connection.connect();

      try {
        LoggingUtils.d(LOG_TAG, "LogoutResponse" + connection.toString());
        response = readFromStream(connection.getInputStream());
      } catch (MalformedURLException e) {
        LoggingUtils.e(
            LOG_TAG,
            "Error reading stream \""
                + connection.getInputStream()
                + "\". "
                + e.getLocalizedMessage(),
            null);
      } catch (IOException e) {
        response = readFromStream(connection.getErrorStream());
      } finally {
        connection.disconnect();
      }

      // Allow for calls to return nothing
      if (response.length() == 0) {
        return "";
      }

      // Check for JSON parsing errors (will throw JSONException is can't be parsed)
      JSONObject object = new JSONObject(response);

      // If no error, return response
      if (!object.has("error")) {
        return response;
      }
      // If there is a refresh token error, refresh the token
      else if (object.getString("error").equals("invalid_token")) {
        if (refreshLimitReached) {
          // Give up
          return response;
        } else {
          // Refresh the token
          WebServiceAuthProvider.refreshAccessToken(context);
          refreshed++;
        }
      }
    } // while(!refreshLimitReached)

    return response;
  }
  /**
   * Synchronous call to get a new client credentials token, required for creating new account
   *
   * @param url
   * @param clientCredentialsToken
   * @param httpMethod
   * @param httpBody
   * @return The data from the server as a string, in almost all cases JSON
   * @throws MalformedURLException
   * @throws IOException
   * @throws ProtocolException
   * @throws JSONException
   */
  public static String getClientCredentialsResponse(
      Context context,
      String url,
      String clientCredentialsToken,
      String httpMethod,
      Bundle httpBody)
      throws MalformedURLException, IOException, ProtocolException, JSONException {
    boolean refreshLimitReached = false;
    int refreshed = 0;

    String response = "";
    while (!refreshLimitReached) {
      // If we have refreshed max number of times, we will not do so again
      if (refreshed == 1) {
        refreshLimitReached = true;
      }

      HttpsURLConnection connection = createSecureConnection(new URL(addParameters(context, url)));
      connection.setRequestMethod(httpMethod);
      connection.setDoOutput(true);
      connection.setDoInput(true);
      String authValue = "Bearer " + clientCredentialsToken;
      connection.setRequestProperty("Authorization", authValue);
      connection.connect();

      if (!httpBody.isEmpty()) {
        OutputStream os = new BufferedOutputStream(connection.getOutputStream());
        os.write(encodePostBody(httpBody).getBytes());
        os.flush();
      }

      try {
        LoggingUtils.d(LOG_TAG, connection.toString());
        response = readFromStream(connection.getInputStream());
      } catch (FileNotFoundException e) {
        response = readFromStream(connection.getErrorStream());
      } finally {
        connection.disconnect();
      }

      // Allow for calls to return nothing
      if (response.length() == 0) {
        return "";
      }

      // Check for JSON parsing errors (will throw JSONException is can't be parsed)
      JSONObject object = new JSONObject(response);

      // If no error, return response
      if (!object.has("error")) {
        return response;
      }
      // If there is a refresh token error, refresh the token
      else if (object.getString("error").equals("invalid_token")) {
        if (refreshLimitReached) {
          // Give up
          return response;
        } else {
          // Refresh the token
          WebServiceAuthProvider.refreshAccessToken(context);
          refreshed++;
        }
      }
    } // while(!refreshLimitReached)

    return response;
  }
  /**
   * Synchronous call to the OCC web services
   *
   * @param url The url
   * @param isAuthorizedRequest Whether this request requires the authorization token sending
   * @param httpMethod method type (GET, PUT, POST, DELETE)
   * @param httpBody Data to be sent in the body (Can be empty)
   * @return The data from the server as a string, in almost all cases JSON
   * @throws MalformedURLException
   * @throws IOException
   * @throws ProtocolException
   */
  public static String getResponse(
      Context context, String url, Boolean isAuthorizedRequest, String httpMethod, Bundle httpBody)
      throws MalformedURLException, IOException, ProtocolException, JSONException {
    // Refresh if necessary
    if (isAuthorizedRequest && WebServiceAuthProvider.tokenExpiredHint(context)) {
      WebServiceAuthProvider.refreshAccessToken(context);
    }

    boolean refreshLimitReached = false;
    int refreshed = 0;

    String response = "";
    while (!refreshLimitReached) {
      // If we have refreshed max number of times, we will not do so again
      if (refreshed == 1) {
        refreshLimitReached = true;
      }

      // Make the connection and get the response
      OutputStream os;
      HttpURLConnection connection;

      if (httpMethod.equals("GET") && httpBody != null && !httpBody.isEmpty()) {
        url = url + "?" + encodePostBody(httpBody);
      }
      URL requestURL = new URL(addParameters(context, url));

      if (StringUtils.equalsIgnoreCase(requestURL.getProtocol(), "https")) {
        HttpsURLConnection https = createSecureConnection(requestURL);
        if (isAuthorizedRequest) {
          String authValue =
              "Bearer " + SDKSettings.getSharedPreferenceString(context, "access_token");
          https.setRequestProperty("Authorization", authValue);
        }
        connection = https;
      } else {
        connection = createConnection(requestURL);
      }
      connection.setRequestMethod(httpMethod);

      if (!httpMethod.equals("GET") && !httpMethod.equals("DELETE")) {
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.connect();

        if (httpBody != null && !httpBody.isEmpty()) {
          os = new BufferedOutputStream(connection.getOutputStream());
          os.write(encodePostBody(httpBody).getBytes());
          os.flush();
        }
      }

      response = "";
      try {
        LoggingUtils.d(LOG_TAG, connection.toString());
        response = readFromStream(connection.getInputStream());
      } catch (FileNotFoundException e) {
        LoggingUtils.e(
            LOG_TAG,
            "Error reading stream \""
                + connection.getInputStream()
                + "\". "
                + e.getLocalizedMessage(),
            context);
        response = readFromStream(connection.getErrorStream());
      } finally {
        connection.disconnect();
      }

      // Allow for calls to return nothing
      if (response.length() == 0) {
        return "";
      }

      // Check for JSON parsing errors (will throw JSONException is can't be parsed)
      JSONObject object = new JSONObject(response);

      // If no error, return response
      if (!object.has("error")) {
        return response;
      }
      // If there is a refresh token error, refresh the token
      else if (object.getString("error").equals("invalid_token")) {
        if (refreshLimitReached) {
          // Give up
          return response;
        } else {
          // Refresh the token
          WebServiceAuthProvider.refreshAccessToken(context);
          refreshed++;
        }
      }
    } // while(!refreshLimitReached)

    // There is an error other than a refresh error, so return the response
    return response;
  }