package org.eclipse.osbp.xtext.functionlibrary.common.http;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HttpClient {
	private static final String ACCEPT = "Accept";
	private static final String APPLICATION_JSON = "application/json";
	/** The LOGGER. */
	protected static final Logger LOGGER = LoggerFactory
			.getLogger(HttpClient.class);

	private HttpClient() {
	}

	public static String httpGet(String remoteHost, int remotePort, String path) {
		return httpGet(remoteHost, remotePort, path, null, ' ');
	}
	
	public static String httpGet(String remoteHost, int remotePort, String path, Map<String, String> paras) {
		return httpGet(remoteHost, remotePort, path, paras, ' ');
	}

	public static String httpGet(String remoteHost, int remotePort, String path, Map<String, String> paras, char parameterSeparator) {
		String responseString = null;
		URIBuilder builder = new URIBuilder();
		builder.setScheme("http").setHost(remoteHost).setPort(remotePort);
		builder.setPath(path);
		createQuery(builder, paras, parameterSeparator);
		try {
			HttpGet get = new HttpGet(builder.build());
			get.addHeader(ACCEPT, APPLICATION_JSON);
			CloseableHttpClient httpClient = HttpClientBuilder.create().build();
			CloseableHttpResponse response = httpClient.execute(get);
			responseString = EntityUtils.toString(response.getEntity());
			// in case a python strings are returned - change to normal quotes  
			if(StringUtils.countMatches(responseString, "'") %2 == 0) {
				responseString = responseString.replace("'", "\"");
			}
			get.releaseConnection();
		} catch (URISyntaxException | ParseException | IOException e) {
			LOGGER.error("{}", e);
		}
		return responseString;
	}

	private static void createQuery(URIBuilder builder, Map<String, String> paras, char parameterSeparator) {
		builder.clearParameters();
		if(paras != null) {
			if(parameterSeparator == ' ') {
				for(Entry<String, String> para:paras.entrySet()) {
					builder.addParameter(para.getKey(), para.getValue());
				}
			} else {
				List<NameValuePair> params = new ArrayList<>();
				for(Entry<String, String> para:paras.entrySet()) {
					params.add(new BasicNameValuePair(para.getKey(), para.getValue()));
				}
				builder.setCustomQuery(URLEncodedUtils.format(params, parameterSeparator, Consts.UTF_8));
			}
		}
	}

	public static void httpPut(String remoteHost, int remotePort, String path, Map<String, String> paras) {
		httpPut(remoteHost, remotePort, path, paras, ' ');
	}
	
	public static void httpPut(String remoteHost, int remotePort, String path, Map<String, String> paras, char parameterSeparator) {
		URIBuilder builder = new URIBuilder(); 
		builder.setScheme("http").setHost(remoteHost).setPort(remotePort);
		builder.setPath(path);
		createQuery(builder, paras, parameterSeparator);
		try {
			HttpPut put = new HttpPut(builder.build());
			put.addHeader(ACCEPT, APPLICATION_JSON);
			CloseableHttpClient httpClient = HttpClientBuilder.create().build();
			CloseableHttpResponse response = httpClient.execute(put);
			if(LOGGER.isDebugEnabled()) {
				LOGGER.debug(EntityUtils.toString(response.getEntity()));
			}
			put.releaseConnection();
		} catch (URISyntaxException | ParseException | IOException e) {
			LOGGER.error("{}", e);
		}
	}

	public static void httpPost(String remoteHost, int remotePort, String path) {
		httpPost(remoteHost, remotePort, path, null);
	}
	
	public static void httpPost(String remoteHost, int remotePort, String path, Map<String, Object> paras) {
		URIBuilder builder = new URIBuilder();
		builder.setScheme("http").setHost(remoteHost).setPort(remotePort);
		builder.setPath(path);
		try {
			HttpPost post = new HttpPost(builder.build());
			post.addHeader(ACCEPT, APPLICATION_JSON);
			if(paras != null) {
				MultipartEntityBuilder mpeBuilder = MultipartEntityBuilder.create();
				mpeBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
				post.setEntity(mpeBuilder.build());
				for(Entry<String, Object> para:paras.entrySet()) {
					if(para.getValue() instanceof String) {
						mpeBuilder.addTextBody(para.getKey(), (String)para.getValue());
					}
					if(para.getValue() instanceof byte[]) {
						mpeBuilder.addBinaryBody(para.getKey(), (byte[]) para.getValue(), ContentType.MULTIPART_FORM_DATA, "");
					}
				}
				post.setEntity(mpeBuilder.build());
			}
			CloseableHttpClient httpClient = HttpClientBuilder.create().build();
			CloseableHttpResponse response = httpClient.execute(post);
			if(LOGGER.isDebugEnabled()) {
				LOGGER.debug(EntityUtils.toString(response.getEntity()));
			}
			post.releaseConnection();
		} catch (URISyntaxException | ParseException | IOException e) {
			LOGGER.error("{}", e);
		}
	}

}
