package com.mv.hr.client;

import java.net.URI;

import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;

import org.apache.log4j.Logger;

import com.mv.base.exception.ThirdPartyBadResponseException;
import com.mv.base.exception.ThirdPartyConnectivityFailureException;

public abstract class ActionPerformer {
	private static final Logger LOG = Logger.getLogger(ActionPerformer.class);

	protected URI urlPath;
	protected Builder request;

	public ActionPerformer(Client webClient, UriBuilder uriBuilder, Object... uriParams) {
		this.urlPath = uriBuilder.build(uriParams);
		this.request = getRequest(webClient);
	}

	private Builder getRequest(Client webClient) {
		WebTarget webResource = webClient.target(urlPath);
		return webResource.request(MediaType.APPLICATION_JSON_TYPE);
	}

	public <T> T getResponse(Class<T> resultClass) throws ThirdPartyBadResponseException, ThirdPartyConnectivityFailureException {
		Response response = this.act();
		response.bufferEntity();
		assertResponseValidity(response);
		return parseResponse(response, resultClass);
	}

	protected abstract Response act() throws ThirdPartyConnectivityFailureException;

	private <T> T parseResponse(Response response, Class<T> resultClass) throws ThirdPartyBadResponseException {
		try {
			return response.readEntity(resultClass);
		} catch (ProcessingException e) {
			String message = e.getMessage();

			Throwable cause = e.getCause();
			if (cause != null) {
				message += "; " + cause.getMessage();
			}

			logDebugInfo(response, message);

			throw new ThirdPartyBadResponseException(message, response, e);
		}
	}

	private void logDebugInfo(Response response, String message) {
		String headers = response.getHeaders().toString();
		int status = response.getStatus();

		String body;
		try {
			body = response.readEntity(String.class);
		} catch (Exception e){
			body = "Can't read the body";
		}

		LOG.error("Failed parsing the response from " + urlPath + ", message: " + message);
		LOG.debug(urlPath);
		LOG.debug(status);
		LOG.debug(headers);
		LOG.debug(body);
	}

	private void assertResponseValidity(Response response) throws ThirdPartyBadResponseException {
		if (response.getStatusInfo().getFamily() != Response.Status.Family.SUCCESSFUL) {
			String responseString = response.readEntity(String.class);
			String errorMessage = urlPath + " returned unsuccessful response, status: " + response.getStatus();

			LOG.error(errorMessage + "; response: " + responseString);
			throw new ThirdPartyBadResponseException(errorMessage, response);
		}
	}
}

@@ -1151,35 +1151,8 @@
 ();%0A
-%09%09response.bufferEntity();%0A
 %09%09as
@@ -2327,16 +2327,184 @@
 ption %7B%0A
+%09%09String errorMessage = null;%0A%0A%09%09try %7B%0A%09%09%09response.bufferEntity();%0A%09%09%7D catch (ProcessingException e) %7B%0A%09%09%09errorMessage = urlPath + %22 returned malformed response%22;%0A%09%09%7D%0A%0A
 %09%09if (re
@@ -2585,77 +2585,8 @@
 %0A%09%09%09
-String responseString = response.readEntity(String.class);%0A%09%09%09String 
 erro
@@ -2678,22 +2678,73 @@
 ();%0A
-%0A
 %09%09%09
-LOG.error(
+String responseString = response.readEntity(String.class);%0A%09%09%09
 erro
@@ -2753,16 +2753,17 @@
 essage +
+=
  %22; resp
@@ -2786,16 +2786,78 @@
 seString
+;%0A%09%09%7D%0A%0A%09%09if (errorMessage != null) %7B%0A%09%09%09LOG.error(errorMessage
 );%0A%09%09%09th

Fix buffering malformed response