package com.xxl.job.core.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;

public class HttpClientUtil {

	public static UrlEncodedFormEntity getPostParam(Map<String, String> param) throws UnsupportedEncodingException {
		List<NameValuePair> params = getReqParamNVP(param);
		// 编码格式转换
		return new UrlEncodedFormEntity(params, "utf-8");
	}

	@SuppressWarnings("unchecked")
	public static List<NameValuePair> getReqParamNVP(Map<String, String> param) {
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		Iterator it = param.entrySet().iterator();
		while (it.hasNext()) {
			java.util.Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next();

			params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));// entry.getKey()
																					// 返回与此项对应的键,entry.getValue()，返回与此项对应的值，logger.info(entry.getValue());
		}
		return params;
	}

	public static Map<String, String> submitPostRequest(String url, Map<String, String> postParamMap,
			Map<String, String> requestHeaderMap) throws UnsupportedEncodingException {
		return submitPostRequest(url, getPostParam(postParamMap), requestHeaderMap);

	}

	/**
	 * 提交 POST 请求到服务器
	 * 
	 * @param requestType
	 *                        请求业务类型
	 * @param url
	 *                        要POST的url，如果参数不多的话可以将参数直接设置到url中
	 * @param cookie
	 * @param referer
	 * @param param
	 *                        要post到服务器的参数
	 * @return POST后的 response和cookie
	 */
	public static Map<String, String> submitPostRequest(String url, UrlEncodedFormEntity param,
			Map<String, String> requestHeaderMap) {

		// logger.info("begin submitPostRequest url=" + url);
		HttpPost post = new HttpPost(url);
		CloseableHttpResponse response = null;
		InputStream is = null;
		CloseableHttpClient client = getHttpClient();
		HashMap<String, String> resultMap = new HashMap<String, String>();
		try {
			setRequestHeader(requestHeaderMap, post);
			if (param != null) {
				post.setEntity(param);

			}

			response = client.execute(post);
			String jsessoiId = parseJesssionId(response);
			resultMap.put("Cookie", jsessoiId);
			resultMap.put("status", response.getStatusLine().getStatusCode() + "");
			HttpEntity entity = response.getEntity();
			if (entity != null) {

				is = entity.getContent();// start 读取整个页面内容
				resultMap.put("responseMessage", readResponseInStream(is)); // end
																			// 读取整个页面内容
			}

		} catch (java.net.ConnectException e) {
			// logger.error("网络异常：url=" + url + " 错误消息:" + e.getMessage());
			// e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
			// logger.error(e.getMessage() + " URL=" + url);
			// e.printStackTrace();
		} finally {
			try {
				if (is != null) {
					is.close();
				}
				if (response != null) {
					response.close();
				}
				post.releaseConnection();
				client.close();
			} catch (Exception e) {
				// e.printStackTrace();
			}
		}

		return resultMap;
	}

	public static CloseableHttpClient getHttpClient() {

		PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
		cm.setMaxTotal(200);// 连接池最大并发连接数
		cm.setDefaultMaxPerRoute(50);// 单路由最大并发数

		CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();

		return httpClient;
	}

	private static void setRequestHeader(Map<String, String> requestHeaderMap, HttpPost post) {
		if (requestHeaderMap != null) {
			Iterator iter = requestHeaderMap.entrySet().iterator();
			while (iter.hasNext()) {
				Map.Entry<String, String> entry = (Map.Entry<String, String>) iter.next();
				if (entry.getValue() != null) {
					post.setHeader(entry.getKey(), entry.getValue());

				}
			}
		}
	}

	private static String parseJesssionId(CloseableHttpResponse response) {
		String result = "";
		if (response.getHeaders("Set-Cookie") != null && response.getHeaders("Set-Cookie").length > 0) {
			String cookieSession = response.getHeaders("Set-Cookie")[0].toString();
			String[] cookies = cookieSession.split(";");
			for (String cookie : cookies) {
				int jsessionIndex = cookie.indexOf("JSESSIONID");
				if (jsessionIndex > 0) {
					return cookie.substring(jsessionIndex, cookie.length());
				}
			}
		}
		return result;
	}

	private static String readResponseInStream(InputStream is) throws IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(is));
		StringBuffer buffer = new StringBuffer();
		String line = "";
		while ((line = in.readLine()) != null) {
			buffer.append(line);
		}
		return buffer.toString();
	}

	public static String postTaskJob(String url, String apiName) {

		Map<String, String> params = new HashMap<String, String>();
		Map<String, String> resultMap = new HashMap<>();
		try {
			Map<String, String> sessoinMap = submitPostRequest(url, params, null);
			String session = sessoinMap.get("Cookie");
			if (session != null && !session.equals("")) {
				Map<String, String> cookieMap = new HashMap<String, String>();
				cookieMap.put("Cookie", session);
				HashMap<String, String> paramsw = new HashMap<String, String>();
				paramsw.put("apiparams", "{}");
				resultMap = submitPostRequest(url + apiName, paramsw, cookieMap);
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return resultMap.get("responseMessage");

	}

	public static void main(String[] args) {
		String responseMessage = postTaskJob("http://localhost:8080/weixt/api/", "readexam_findBookExamList");
		System.out.println(responseMessage);
	}

}
