package com.mx.dla.dda.restClient.bos;

import java.io.IOException;
import java.net.SocketTimeoutException;

import org.apache.log4j.Logger;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;

import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;

public class DLARestClient {

	private RestTemplate template;
	private String uri;
	private static Logger log = Logger.getLogger(DLARestClient.class);

	public DLARestClient(String uri) throws SocketTimeoutException, IOException, TransaccionException {
		try {
			HttpComponentsClientHttpRequestFactory client = new HttpComponentsClientHttpRequestFactory();
			client.setReadTimeout(60000 * 10);
			client.setConnectTimeout(60000 * 10);
			template = new RestTemplate(client);

			template.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
			template.getMessageConverters().add(new StringHttpMessageConverter());
			template.getInterceptors().add(new HeaderRequestInterceptor("Accept", MediaType.APPLICATION_JSON_VALUE));
			template.getInterceptors()
					.add(new HeaderRequestInterceptor("Content-Type", MediaType.APPLICATION_JSON_VALUE));
			this.uri = uri;
		} catch (HttpClientErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpServerErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (ResourceAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotReadableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotWritableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}

	}

	public <T> T get(Class<T> responseType) throws SocketTimeoutException, IOException, TransaccionException {

		try {
			HttpComponentsClientHttpRequestFactory client = new HttpComponentsClientHttpRequestFactory();
			client.setReadTimeout(60000 * 10);
			client.setConnectTimeout(60000 * 10);
			template = new RestTemplate(client);

			template.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
			template.getMessageConverters().add(new StringHttpMessageConverter());
			template.getInterceptors().add(new HeaderRequestInterceptor("Accept", MediaType.APPLICATION_JSON_VALUE));
			template.getInterceptors()
					.add(new HeaderRequestInterceptor("Content-Type", MediaType.APPLICATION_JSON_VALUE));

			T r = template.postForObject(uri, "", responseType);

			client.destroy();
			return r;
		} catch (HttpClientErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpServerErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (ResourceAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotReadableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotWritableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public <T> T get(Object request, Class<T> responseType) throws SocketTimeoutException, IOException, TransaccionException {

		try {
			HttpComponentsClientHttpRequestFactory client = new HttpComponentsClientHttpRequestFactory();
			client.setReadTimeout(60000 * 10);
			client.setConnectTimeout(60000 * 10);
			template = new RestTemplate(client);

			template.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
			template.getMessageConverters().add(new StringHttpMessageConverter());
			template.getInterceptors().add(new HeaderRequestInterceptor("Accept", MediaType.APPLICATION_JSON_VALUE));
			template.getInterceptors()
					.add(new HeaderRequestInterceptor("Content-Type", MediaType.APPLICATION_JSON_VALUE));
			T r = template.postForObject(uri, request, responseType);

			client.destroy();
			return r;
		} catch (HttpClientErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpServerErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (ResourceAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotReadableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotWritableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public <T> T get(String request, Class<T> responseType) throws SocketTimeoutException, IOException, TransaccionException {

		try {
			HttpComponentsClientHttpRequestFactory client = new HttpComponentsClientHttpRequestFactory();
			client.setReadTimeout(60000 * 10);
			client.setConnectTimeout(60000 * 10);
			template = new RestTemplate(client);

			template.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
			template.getMessageConverters().add(new StringHttpMessageConverter());
			log.info("URL: " + uri.concat(request));
			T r = template.getForObject(uri.concat(request), responseType);

			client.destroy();
			return r;
		} catch (HttpClientErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpServerErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (ResourceAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotReadableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotWritableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public <T> T getJson(String request, Class<T> responseType) throws SocketTimeoutException, IOException, TransaccionException {

		try {
			HttpComponentsClientHttpRequestFactory client = new HttpComponentsClientHttpRequestFactory();
			client.setReadTimeout(60000 * 10);
			client.setConnectTimeout(60000 * 10);
			template = new RestTemplate(client);

			template.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
			template.getMessageConverters().add(new StringHttpMessageConverter());
			template.getInterceptors().add(new HeaderRequestInterceptor("Accept", MediaType.APPLICATION_JSON_VALUE));
			template.getInterceptors()
					.add(new HeaderRequestInterceptor("Content-Type", MediaType.APPLICATION_JSON_VALUE));
			log.info("URL: " + uri.concat(request));
			T r = template.getForObject(uri.concat(request), responseType);

			client.destroy();
			return r;
		} catch (HttpClientErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpServerErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (ResourceAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotReadableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotWritableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public <T> T getBv(String request, Class<T> responseType) throws SocketTimeoutException, IOException, TransaccionException {

		try {
			HttpComponentsClientHttpRequestFactory client = new HttpComponentsClientHttpRequestFactory();
			client.setReadTimeout(60000 * 10);
			client.setConnectTimeout(60000 * 10);
			template = new RestTemplate(client);

			template.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
			template.getMessageConverters().add(new StringHttpMessageConverter());
			template.getInterceptors().add(new HeaderRequestInterceptor("Accept", MediaType.APPLICATION_JSON_VALUE));
			log.info("URL: " + uri.concat(request));
			T r = template.getForObject(uri.concat(request), responseType);

			client.destroy();
			return r;
		} catch (HttpClientErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpServerErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (ResourceAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotReadableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotWritableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public void get(Object request) throws SocketTimeoutException, IOException, TransaccionException {

		try {
			HttpComponentsClientHttpRequestFactory client = new HttpComponentsClientHttpRequestFactory();
			client.setReadTimeout(60000 * 5);
			client.setConnectTimeout(60000 * 5);
			template = new RestTemplate(client);

			template.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
			template.getMessageConverters().add(new StringHttpMessageConverter());
			template.getInterceptors().add(new HeaderRequestInterceptor("Accept", MediaType.APPLICATION_JSON_VALUE));
			template.getInterceptors()
					.add(new HeaderRequestInterceptor("Content-Type", MediaType.APPLICATION_JSON_VALUE));
			template.postForObject(uri, request, Void.class);

			client.destroy();
		} catch (HttpClientErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpServerErrorException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (ResourceAccessException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotReadableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		} catch (HttpMessageNotWritableException e) {
			throw new TransaccionException("Error al cargar los datos", e);
		}
	}

	public String getUri() {
		return uri;
	}

}
