/**
   * Obtains a parameter with specified name from from query string. The query should be in format
   * param=value&param=value ...
   *
   * @param query Queery in "url" format.
   * @param paramName Parameter name.
   * @return Parameter value, or null.
   */
  public static String getParameterValueFromQuery(String query, String paramName) {
    String[] components = query.split("&");

    for (String keyValuePair : components) {
      String[] pairComponents = keyValuePair.split("=");

      if (pairComponents.length == 2) {
        try {
          String key = URLDecoder.decode(pairComponents[0], "utf-8");
          if (key.compareTo(paramName) == 0) {
            return URLDecoder.decode(pairComponents[1], "utf-8");
          }
        } catch (UnsupportedEncodingException e) {
          logger.error(
              "getParameterValueFromQuery failed with exception: " + e.getLocalizedMessage(), e);
        }
      }
    }

    return null;
  }
  /**
   * Extracts a JSON object from server response with secured string.
   *
   * @param response Server response
   * @return Extracted secured JSON or null.
   */
  public static JSONObject extractSecureJson(Response response) {
    try {
      String responseText = response.getResponseText();

      if (!responseText.startsWith(SECURE_PATTERN_START)
          || !responseText.endsWith(SECURE_PATTERN_END)) {
        return null;
      }

      int startIndex = responseText.indexOf(SECURE_PATTERN_START);
      int endIndex =
          responseText.indexOf(
              SECURE_PATTERN_END, responseText.length() - SECURE_PATTERN_END.length() - 1);

      String jsonString =
          responseText.substring(startIndex + SECURE_PATTERN_START.length(), endIndex);

      return new JSONObject(jsonString);
    } catch (Throwable t) {
      logger.error("extractSecureJson failed with exception: " + t.getLocalizedMessage(), t);
      return null;
    }
  }
/** Internal helper class with various utilities. */
public class Utils {
  private static Logger logger = Logger.getInstance("Utils");
  private static final String SECURE_PATTERN_START = "/*-secure-\n";
  private static final String SECURE_PATTERN_END = "*/";

  private static final String BLUEMIX_NAME = "bluemix";
  private static final String BLUEMIX_DOMAIN = "bluemix.net";
  private static final String STAGE1_NAME = "stage1";

  /**
   * Obtains a parameter with specified name from from query string. The query should be in format
   * param=value&param=value ...
   *
   * @param query Queery in "url" format.
   * @param paramName Parameter name.
   * @return Parameter value, or null.
   */
  public static String getParameterValueFromQuery(String query, String paramName) {
    String[] components = query.split("&");

    for (String keyValuePair : components) {
      String[] pairComponents = keyValuePair.split("=");

      if (pairComponents.length == 2) {
        try {
          String key = URLDecoder.decode(pairComponents[0], "utf-8");
          if (key.compareTo(paramName) == 0) {
            return URLDecoder.decode(pairComponents[1], "utf-8");
          }
        } catch (UnsupportedEncodingException e) {
          logger.error(
              "getParameterValueFromQuery failed with exception: " + e.getLocalizedMessage(), e);
        }
      }
    }

    return null;
  }

  /**
   * Extracts a JSON object from server response with secured string.
   *
   * @param response Server response
   * @return Extracted secured JSON or null.
   */
  public static JSONObject extractSecureJson(Response response) {
    try {
      String responseText = response.getResponseText();

      if (!responseText.startsWith(SECURE_PATTERN_START)
          || !responseText.endsWith(SECURE_PATTERN_END)) {
        return null;
      }

      int startIndex = responseText.indexOf(SECURE_PATTERN_START);
      int endIndex =
          responseText.indexOf(
              SECURE_PATTERN_END, responseText.length() - SECURE_PATTERN_END.length() - 1);

      String jsonString =
          responseText.substring(startIndex + SECURE_PATTERN_START.length(), endIndex);

      return new JSONObject(jsonString);
    } catch (Throwable t) {
      logger.error("extractSecureJson failed with exception: " + t.getLocalizedMessage(), t);
      return null;
    }
  }

  /**
   * Builds rewrite domain from backend route url.
   *
   * @param backendRoute Backend route.
   * @param subzone Subzone
   * @return Rewrite domain.
   * @throws MalformedURLException if backendRoute parameter has invalid format.
   */
  public static String buildRewriteDomain(String backendRoute, String subzone)
      throws MalformedURLException {
    if (backendRoute == null || backendRoute.isEmpty()) {
      logger.error("Backend route can't be null.");
      return null;
    }

    String applicationRoute = backendRoute;

    if (!applicationRoute.startsWith(BMSClient.HTTP_SCHEME)) {
      applicationRoute = String.format("%s://%s", BMSClient.HTTPS_SCHEME, applicationRoute);
    } else if (!applicationRoute.startsWith(BMSClient.HTTPS_SCHEME)
        && applicationRoute.contains(BLUEMIX_NAME)) {
      applicationRoute = applicationRoute.replace(BMSClient.HTTP_SCHEME, BMSClient.HTTPS_SCHEME);
    }

    URL url = new URL(applicationRoute);

    String host = url.getHost();
    String rewriteDomain;
    String regionInDomain = "ng";
    int port = url.getPort();

    String serviceUrl = String.format("%s://%s", url.getProtocol(), host);

    if (port != 0) {
      serviceUrl += ":" + String.valueOf(port);
    }

    String[] hostElements = host.split("\\.");

    if (!serviceUrl.contains(STAGE1_NAME)) {
      // Multi-region: myApp.eu-gb.mybluemix.net
      // US: myApp.mybluemix.net
      if (hostElements.length == 4) {
        regionInDomain = hostElements[hostElements.length - 3];
      }

      // this is production, because STAGE1 is not found
      // Multi-Region Eg: eu-gb.bluemix.net
      // US Eg: ng.bluemix.net
      rewriteDomain = String.format("%s.%s", regionInDomain, BLUEMIX_DOMAIN);
    } else {
      // Multi-region: myApp.stage1.eu-gb.mybluemix.net
      // US: myApp.stage1.mybluemix.net
      if (hostElements.length == 5) {
        regionInDomain = hostElements[hostElements.length - 3];
      }

      if (subzone != null && !subzone.isEmpty()) {
        // Multi-region Dev subzone Eg: stage1-Dev.eu-gb.bluemix.net
        // US Dev subzone Eg: stage1-Dev.ng.bluemix.net
        rewriteDomain =
            String.format("%s-%s.%s.%s", STAGE1_NAME, subzone, regionInDomain, BLUEMIX_DOMAIN);
      } else {
        // Multi-region Eg: stage1.eu-gb.bluemix.net
        // US  Eg: stage1.ng.bluemix.net
        rewriteDomain = String.format("%s.%s.%s", STAGE1_NAME, regionInDomain, BLUEMIX_DOMAIN);
      }
    }

    return rewriteDomain;
  }

  /**
   * Concatenates two URLs. The function checks for trailing and preceding slashes in rootUrl and
   * path.
   *
   * @param rootUrl first part of the url
   * @param path second part of the url
   * @return Concatenated string containing rootUrl and path.
   */
  public static String concatenateUrls(String rootUrl, String path) {
    if (rootUrl == null || rootUrl.isEmpty()) {
      return path;
    }

    if (path == null || path.isEmpty()) {
      return rootUrl;
    }

    String finalUrl;

    if (rootUrl.charAt(rootUrl.length() - 1) == '/' && path.charAt(0) == '/') {
      finalUrl = rootUrl.substring(0, rootUrl.length() - 2) + path;
    } else if (rootUrl.charAt(rootUrl.length() - 1) != '/' && path.charAt(0) != '/') {
      finalUrl = rootUrl + "/" + path;
    } else {
      finalUrl = rootUrl + path;
    }

    return finalUrl;
  }
}
  /**
   * Builds rewrite domain from backend route url.
   *
   * @param backendRoute Backend route.
   * @param subzone Subzone
   * @return Rewrite domain.
   * @throws MalformedURLException if backendRoute parameter has invalid format.
   */
  public static String buildRewriteDomain(String backendRoute, String subzone)
      throws MalformedURLException {
    if (backendRoute == null || backendRoute.isEmpty()) {
      logger.error("Backend route can't be null.");
      return null;
    }

    String applicationRoute = backendRoute;

    if (!applicationRoute.startsWith(BMSClient.HTTP_SCHEME)) {
      applicationRoute = String.format("%s://%s", BMSClient.HTTPS_SCHEME, applicationRoute);
    } else if (!applicationRoute.startsWith(BMSClient.HTTPS_SCHEME)
        && applicationRoute.contains(BLUEMIX_NAME)) {
      applicationRoute = applicationRoute.replace(BMSClient.HTTP_SCHEME, BMSClient.HTTPS_SCHEME);
    }

    URL url = new URL(applicationRoute);

    String host = url.getHost();
    String rewriteDomain;
    String regionInDomain = "ng";
    int port = url.getPort();

    String serviceUrl = String.format("%s://%s", url.getProtocol(), host);

    if (port != 0) {
      serviceUrl += ":" + String.valueOf(port);
    }

    String[] hostElements = host.split("\\.");

    if (!serviceUrl.contains(STAGE1_NAME)) {
      // Multi-region: myApp.eu-gb.mybluemix.net
      // US: myApp.mybluemix.net
      if (hostElements.length == 4) {
        regionInDomain = hostElements[hostElements.length - 3];
      }

      // this is production, because STAGE1 is not found
      // Multi-Region Eg: eu-gb.bluemix.net
      // US Eg: ng.bluemix.net
      rewriteDomain = String.format("%s.%s", regionInDomain, BLUEMIX_DOMAIN);
    } else {
      // Multi-region: myApp.stage1.eu-gb.mybluemix.net
      // US: myApp.stage1.mybluemix.net
      if (hostElements.length == 5) {
        regionInDomain = hostElements[hostElements.length - 3];
      }

      if (subzone != null && !subzone.isEmpty()) {
        // Multi-region Dev subzone Eg: stage1-Dev.eu-gb.bluemix.net
        // US Dev subzone Eg: stage1-Dev.ng.bluemix.net
        rewriteDomain =
            String.format("%s-%s.%s.%s", STAGE1_NAME, subzone, regionInDomain, BLUEMIX_DOMAIN);
      } else {
        // Multi-region Eg: stage1.eu-gb.bluemix.net
        // US  Eg: stage1.ng.bluemix.net
        rewriteDomain = String.format("%s.%s.%s", STAGE1_NAME, regionInDomain, BLUEMIX_DOMAIN);
      }
    }

    return rewriteDomain;
  }