// Path: src/main/com/sailthru/client/LastRateLimitInfo.java
// public class LastRateLimitInfo {
//     /**
//      * The value of X-Rate-Limit-Limit, representing the limit of requests/minute for this action / method combination
//      */
//     private final int limit;
// 
//     /**
//      * The value of X-Rate-Limit-Remaining, representing how many requests remain in the current minute
//      */
//     private final int remaining;
// 
//     /**
//      * The value of X-rate-Limit-Reset, representing the UNIX epoch timestamp of when the next minute starts, and when the rate limit resets
//      */
//     private final Date reset;
// 
//     public LastRateLimitInfo(int limit, int remaining, Date reset) {
//         this.limit = limit;
//         this.remaining = remaining;
//         this.reset = reset;
//     }
// 
//     public int getLimit() {
//         return limit;
//     }
// 
//     public int getRemaining() {
//         return remaining;
//     }
// 
//     public Date getReset() {
//         return reset;
//     }
// }
// 
// Path: src/main/com/sailthru/client/exceptions/ApiException.java
// @SuppressWarnings("serial")
// public class ApiException extends IOException {
// 
//     private static final String ERRORMSG = "errormsg";
// 
//     private static final Logger logger = LoggerFactory.getLogger(ApiException.class);
// 
//     private Map<String, Object> jsonResponse;
//     private int statusCode;
// 
//     public ApiException(int statusCode, String reason, Map<String, Object> jsonResponse) {
//         super(reason);
//         logger.warn("{}: {}", statusCode, reason);
//         this.jsonResponse = jsonResponse;
//         this.statusCode = statusCode;
//     }
// 
//     public Map<String, Object> getResponse() {
//         return jsonResponse;
//     }
// 
//     public int getStatusCode() {
//         return statusCode;
//     }
// 
//     @SuppressWarnings("unchecked")
//     public static ApiException create(StatusLine statusLine, Object jsonResponse) {
//         return create(statusLine, (Map<String, Object>)jsonResponse);
//     }
// 
//     public static ApiException create(StatusLine statusLine, Map<String, Object> jsonResponse) {
//         if (jsonResponse == null) {
//             jsonResponse = new HashMap<String, Object>();
//         }
// 
//         final String errorMessage = jsonResponse.get(ERRORMSG) == null ? "" :
//             jsonResponse.get(ERRORMSG).toString();
// 
//         return new ApiException(statusLine.getStatusCode(), errorMessage, jsonResponse);
//     }
// }
// 
// Path: src/main/com/sailthru/client/exceptions/ResourceNotFoundException.java
// public class ResourceNotFoundException extends ApiException {
//     public ResourceNotFoundException(int statusCode, String reason,
//             Map<String, Object> jsonResponse) {
//         super(statusCode, reason, jsonResponse);
//     }
// }
// 
// Path: src/main/com/sailthru/client/exceptions/UnAuthorizedException.java
// public class UnAuthorizedException extends ApiException {
//     public UnAuthorizedException(int statusCode, String reason, Map<String, Object> jsonResponse) {
//         super(statusCode, reason, jsonResponse);
//     }
// }


import com.sailthru.client.LastRateLimitInfo;
import com.sailthru.client.exceptions.ApiException;
import com.sailthru.client.exceptions.ResourceNotFoundException;
import com.sailthru.client.exceptions.UnAuthorizedException;
import com.sailthru.client.handler.SailthruResponseHandler;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
package com.sailthru.client.http;



/**
 *
 * @author Prajwal Tuladhar <praj@sailthru.com>
 */
public class SailthruHandler implements ResponseHandler<Object> {

    private SailthruResponseHandler handler;

    private static final Logger logger = LoggerFactory.getLogger(SailthruHandler.class);

    // key used to store rate limit info, for use and removal by the parent SailthruClient
    public static final String RATE_LIMIT_INFO_KEY = "x_rate_limit_info";

    /* Supported HTTP Status codes */
    public static final int STATUS_OK = 200;
    public static final int STATUS_BAD_REQUEST = 400;
    public static final int STATUS_UNAUTHORIZED = 401;
    public static final int STATUS_FORBIDDEN = 403;
    public static final int STATUS_NOT_FOUND = 404;
    public static final int STATUS_METHOD_NOT_FOUND = 405;
    public static final int STATUS_INTERNAL_SERVER_ERROR = 500;

    public SailthruHandler(SailthruResponseHandler handler) {
        super();
        this.handler = handler;
    }

    public Object handleResponse(HttpResponse httpResponse) throws ClientProtocolException, IOException {
        logger.debug("Received Response: {}", httpResponse.toString());

        StatusLine statusLine = httpResponse.getStatusLine();
        int statusCode = statusLine.getStatusCode();

        String jsonString = null;
        jsonString = EntityUtils.toString(httpResponse.getEntity());
        Object parseObject =  handler.parseResponse(jsonString);

        addRateLimitInfoToResponseObject(httpResponse, parseObject);

        switch (statusCode) {
            case STATUS_OK:
                break;

            case STATUS_BAD_REQUEST:
// Path: src/main/com/sailthru/client/LastRateLimitInfo.java
// public class LastRateLimitInfo {
//     /**
//      * The value of X-Rate-Limit-Limit, representing the limit of requests/minute for this action / method combination
//      */
//     private final int limit;
// 
//     /**
//      * The value of X-Rate-Limit-Remaining, representing how many requests remain in the current minute
//      */
//     private final int remaining;
// 
//     /**
//      * The value of X-rate-Limit-Reset, representing the UNIX epoch timestamp of when the next minute starts, and when the rate limit resets
//      */
//     private final Date reset;
// 
//     public LastRateLimitInfo(int limit, int remaining, Date reset) {
//         this.limit = limit;
//         this.remaining = remaining;
//         this.reset = reset;
//     }
// 
//     public int getLimit() {
//         return limit;
//     }
// 
//     public int getRemaining() {
//         return remaining;
//     }
// 
//     public Date getReset() {
//         return reset;
//     }
// }
// 
// Path: src/main/com/sailthru/client/exceptions/ApiException.java
// @SuppressWarnings("serial")
// public class ApiException extends IOException {
// 
//     private static final String ERRORMSG = "errormsg";
// 
//     private static final Logger logger = LoggerFactory.getLogger(ApiException.class);
// 
//     private Map<String, Object> jsonResponse;
//     private int statusCode;
// 
//     public ApiException(int statusCode, String reason, Map<String, Object> jsonResponse) {
//         super(reason);
//         logger.warn("{}: {}", statusCode, reason);
//         this.jsonResponse = jsonResponse;
//         this.statusCode = statusCode;
//     }
// 
//     public Map<String, Object> getResponse() {
//         return jsonResponse;
//     }
// 
//     public int getStatusCode() {
//         return statusCode;
//     }
// 
//     @SuppressWarnings("unchecked")
//     public static ApiException create(StatusLine statusLine, Object jsonResponse) {
//         return create(statusLine, (Map<String, Object>)jsonResponse);
//     }
// 
//     public static ApiException create(StatusLine statusLine, Map<String, Object> jsonResponse) {
//         if (jsonResponse == null) {
//             jsonResponse = new HashMap<String, Object>();
//         }
// 
//         final String errorMessage = jsonResponse.get(ERRORMSG) == null ? "" :
//             jsonResponse.get(ERRORMSG).toString();
// 
//         return new ApiException(statusLine.getStatusCode(), errorMessage, jsonResponse);
//     }
// }
// 
// Path: src/main/com/sailthru/client/exceptions/ResourceNotFoundException.java
// public class ResourceNotFoundException extends ApiException {
//     public ResourceNotFoundException(int statusCode, String reason,
//             Map<String, Object> jsonResponse) {
//         super(statusCode, reason, jsonResponse);
//     }
// }
// 
// Path: src/main/com/sailthru/client/exceptions/UnAuthorizedException.java
// public class UnAuthorizedException extends ApiException {
//     public UnAuthorizedException(int statusCode, String reason, Map<String, Object> jsonResponse) {
//         super(statusCode, reason, jsonResponse);
//     }
// }


// Path: src/main/com/sailthru/client/http/SailthruHandler.java
import com.sailthru.client.LastRateLimitInfo;
import com.sailthru.client.exceptions.ApiException;
import com.sailthru.client.exceptions.ResourceNotFoundException;
import com.sailthru.client.exceptions.UnAuthorizedException;
import com.sailthru.client.handler.SailthruResponseHandler;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

package com.sailthru.client.http;



/**
 *
 * @author Prajwal Tuladhar <praj@sailthru.com>
 */
public class SailthruHandler implements ResponseHandler<Object> {

    private SailthruResponseHandler handler;

    private static final Logger logger = LoggerFactory.getLogger(SailthruHandler.class);

    // key used to store rate limit info, for use and removal by the parent SailthruClient
    public static final String RATE_LIMIT_INFO_KEY = "x_rate_limit_info";

    /* Supported HTTP Status codes */
    public static final int STATUS_OK = 200;
    public static final int STATUS_BAD_REQUEST = 400;
    public static final int STATUS_UNAUTHORIZED = 401;
    public static final int STATUS_FORBIDDEN = 403;
    public static final int STATUS_NOT_FOUND = 404;
    public static final int STATUS_METHOD_NOT_FOUND = 405;
    public static final int STATUS_INTERNAL_SERVER_ERROR = 500;

    public SailthruHandler(SailthruResponseHandler handler) {
        super();
        this.handler = handler;
    }

    public Object handleResponse(HttpResponse httpResponse) throws ClientProtocolException, IOException {
        logger.debug("Received Response: {}", httpResponse.toString());

        StatusLine statusLine = httpResponse.getStatusLine();
        int statusCode = statusLine.getStatusCode();

        String jsonString = null;
        jsonString = EntityUtils.toString(httpResponse.getEntity());
        Object parseObject =  handler.parseResponse(jsonString);

        addRateLimitInfoToResponseObject(httpResponse, parseObject);

        switch (statusCode) {
            case STATUS_OK:
                break;

            case STATUS_BAD_REQUEST:
                throw ApiException.create(statusLine, parseObject);