package com.contentful.java.cma.model;

import java.util.Locale;

import okhttp3.Headers;
import okhttp3.Request;
import okhttp3.Response;

import static java.lang.String.format;

/**
 * This class will represent known Contentful exceptions
 */
public class CMAHttpException extends RuntimeException {
  private final Request request;
  private final Response response;

  /**
   * Construct an error response.
   * <p>
   * This constructor will fill the exception with easy accessible values, like
   * {@link #responseCode()}. {@link #responseMessage()}, but also
   * {@link #rateLimitReset()}.
   *
   * @param request  the request issuing the error.
   * @param response the response from the server to this faulty request.
   */
  public CMAHttpException(Request request, Response response) {
    this.request = request;
    this.response = response;
  }

  /**
   * Convert exception to human readable form.
   *
   * @return a string representing this exception.
   */
  @Override
  public String toString() {
    return format(
        Locale.getDefault(),
        "FAILED REQUEST:\n\t%s\n\t↳ Header{%s}\n\t%s\n\t↳ Header{%s}",
        request.toString(),
        headersToString(request.headers()),
        response.toString(),
        headersToString(response.headers()));
  }

  /**
   * @return the response code of the request.
   */
  public int responseCode() {
    return response.code();
  }

  /**
   * @return the message the server returned.
   */
  public String responseMessage() {
    return response.message();
  }

  /**
   * @return the hourly rate limit or -1 if header not send
   */
  public int rateLimitHourLimit() {
    return parseRateLimitHeader(("X-Contentful-RateLimit-Hour-Limit"));
  }

  /**
   * @return the number of remaining requests that can be made in the hour or -1 if header not send
   */
  public int rateLimitHourRemaining() {
    return parseRateLimitHeader(("X-Contentful-RateLimit-Hour-Remaining"));
  }

  /**
   * @return the per second rate limit or -1 if header not send
   */
  public int rateLimitSecondLimit() {
    return parseRateLimitHeader(("X-Contentful-RateLimit-Second-Limit"));
  }

  /**
   * @return the number of remaining requests that can be made per second or -1 if header not send
   */
  public int rateLimitSecondRemaining() {
    return parseRateLimitHeader(("X-Contentful-RateLimit-Second-Remaining"));
  }

  /**
   * @return the number of seconds until the user can make a next request or -1 if header not send
   */
  public int rateLimitReset() {
    return parseRateLimitHeader(("X-Contentful-RateLimit-Reset"));
  }

  private String headersToString(Headers headers) {
    final StringBuilder builder = new StringBuilder();

    String divider = "";
    for (final String name : headers.names()) {
      final String value = headers.get(name);
      builder.append(divider);
      builder.append(name);
      builder.append(": ");
      builder.append(value);

      if ("".equals(divider)) {
        divider = ", ";
      }
    }

    return builder.toString();
  }

  private int parseRateLimitHeader(String name) {
    try {
      return Integer.parseInt(response.header(name));
    } catch (NumberFormatException e) {
      return -1;
    }
  }
}

@@ -1667,33 +1667,32 @@
 RateLimitHeader(
-(
 %22X-Contentful-Ra
@@ -1703,33 +1703,32 @@
 mit-Hour-Limit%22)
-)
 ;%0A  %7D%0A%0A  /**%0A   
@@ -1894,33 +1894,32 @@
 RateLimitHeader(
-(
 %22X-Contentful-Ra
@@ -1934,33 +1934,32 @@
 Hour-Remaining%22)
-)
 ;%0A  %7D%0A%0A  /**%0A   
@@ -2087,33 +2087,32 @@
 RateLimitHeader(
-(
 %22X-Contentful-Ra
@@ -2133,17 +2133,16 @@
 -Limit%22)
-)
 ;%0A  %7D%0A%0A 
@@ -2317,33 +2317,32 @@
 RateLimitHeader(
-(
 %22X-Contentful-Ra
@@ -2367,17 +2367,16 @@
 aining%22)
-)
 ;%0A  %7D%0A%0A 
@@ -2549,17 +2549,16 @@
 tHeader(
-(
 %22X-Conte
@@ -2580,17 +2580,16 @@
 -Reset%22)
-)
 ;%0A  %7D%0A%0A 

Remove unneccessary double brackets.