package com.ibeetl.admin.flow.utils;

import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;

public final class HttpClientSt {
	private static final Logger logger = LogManager.getLogger(HttpClientSt.class);

	/**
	 * 产生一个HttpClient实例
	 *
	 * @return
     */
	public synchronized static HttpClient getClient() {
		// 根据设置的参数产生一个CloseableHttpClient示例
		CloseableHttpClient httpclient;
		try {
			// 设置超时时间为5秒
			RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(1 * 1000).setSocketTimeout(1 * 1000).build();
			// 请求重试处理
			HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
				public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
					if (executionCount >= 5) {
						// 如果已经重试了5次，就放弃
						return false;
					}
					if (exception instanceof NoHttpResponseException) {
						// 如果服务器丢掉了连接，那么就重试
						return true;
					}
					if (exception instanceof SSLHandshakeException) {
						// 不要重试SSL握手异常
						return false;
					}
					if (exception instanceof InterruptedIOException) {
						// 超时
						return false;
					}
					if (exception instanceof UnknownHostException) {
						// 目标服务器不可达
						return false;
					}
					if (exception instanceof ConnectTimeoutException) {
						// 连接被拒绝
						return false;
					}
					if (exception instanceof SSLException) {
						// ssl握手异常
						return false;
					}

					HttpClientContext clientContext = HttpClientContext.adapt(context);
					HttpRequest request = clientContext.getRequest();
					// 如果请求是幂等的，就再次尝试
                    return !(request instanceof HttpEntityEnclosingRequest);
                }
			};
			httpclient = HttpClients.custom().setDefaultRequestConfig(requestConfig).setRetryHandler(httpRequestRetryHandler).build();
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
		return httpclient;
	}

	/**
	 * 请求系统并获得返回的信息
	 *
	 * @param httpData
	 * @return String
	 * @throws Exception
	 */
	public static String getInfo(HttpData httpData) throws Exception {
		InputStreamReader isr = null;
		long starttime = System.currentTimeMillis();
		try {
			//connectionRequestTimeout  从连接池获取连接的timeout
			//connectionTimeout  和服务器建立连接的timeout
			//socketTimeout  从服务器读取数据的timeout

			HttpClient httpsClient = ConnectPool.createclient(httpData);
			RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(40 * 1000).setConnectTimeout(40 * 1000).build();// 设置请求和传输超时时间
			HttpResponse response = null;
			if (httpData == null) {
				throw new Exception("Parameter<HttpData> is NULL!");
			}
			if ("POST".equals(httpData.getMethod().toUpperCase())) {
				HttpPost htpost = new HttpPost(httpData.getUrl());
				htpost.setConfig(requestConfig);
				logger.info("-------post----");
				if (StringUtils.isNotBlank(httpData.getData())) {
					htpost.addHeader("Content-Type", "text/html");
					htpost.addHeader("ContentLength", String.valueOf(httpData.getData()).length() + "");
					StringEntity entiy = new StringEntity(httpData.getData(), "utf-8");
					// BufferedReader br = new BufferedReader(new
					// InputStreamReader(entiy.getContent()));
					// String s = "";
					// while((s=br.readLine())!=null){
					// System.out.println("getInfo："+s);
					// }
					htpost.setEntity(entiy);
				}
				response = httpsClient.execute(htpost);

			} else {
				HttpGet htget = new HttpGet(httpData.getUrl());
				htget.setConfig(requestConfig);
				response = httpsClient.execute(htget);
			}
			if (response.getStatusLine().getStatusCode() != 200) {
				throw new Exception("Request is fail!");
			}
			isr = new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8);
			BufferedReader br = new BufferedReader(isr);
			StringBuffer content = new StringBuffer();
			for (String line; (line = br.readLine()) != null;) {
				content.append(line);
			}
			String s = content.toString();
			br.close();
			return s.substring(s.lastIndexOf(s.trim()));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (isr != null) {
				isr.close();
			}
			long endtime = System.currentTimeMillis();
			logger.info("此次调用共花费约：" + (endtime - starttime) / 1000 + "" + "秒");
		}
		return "";
	}

	/**
	 * 按流形态请求
	 *
	 * @param httpData
	 * @return
	 * @throws Exception
	 */
	public static String getresult(HttpData httpdata) throws Exception {
		logger.info("begin send");
		String sTotalString = null;
		try {
			if (httpdata == null) {
				throw new Exception("Parameter<HttpData> is NULL!");
			}
			URL url = null;
			HttpURLConnection httpConn = null;
			OutputStream output = null;
			OutputStreamWriter outr = null;
			if (StringUtils.isEmpty(httpdata.getUrl())) {
				throw new Exception("Parameter<Url> is NULL!");
			}
			url = new URL(httpdata.getUrl());
			httpConn = (HttpURLConnection) url.openConnection();
			HttpURLConnection.setFollowRedirects(true);
			httpConn.setDoOutput(true);
			httpConn.setRequestMethod("POST");
			httpConn.setRequestProperty("Content-Type", "application/json");
			httpConn.connect();
			output = httpConn.getOutputStream();
			outr = new OutputStreamWriter(output);
			// 写入请求参数
			outr.write(httpdata.getData().toCharArray(), 0, httpdata.getData().length());
			outr.flush();
			outr.close();

			int code = httpConn.getResponseCode();
			// 读取响应内容
			String sCurrentLine = "";
			sTotalString = "";
			if (code == 200) {
				InputStream is = httpConn.getInputStream();
				BufferedReader reader = new BufferedReader(new InputStreamReader(is));
				while ((sCurrentLine = reader.readLine()) != null)
					if (sCurrentLine.length() > 0)
						sTotalString = sTotalString + sCurrentLine.trim();
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
		return sTotalString;
	}


	/**
	 * 加密传输数据
	 *
	 * @param pwd
	 * @return String
	 * @throws Exception
	 */
	public static String formatXml(String encodeinfo, String pwd) throws Exception {
		encodeinfo = DesUtilTo32.encode(encodeinfo, pwd);
		return encodeinfo;
	}

	/**
	 * 加密传输数据
	 *
	 * @param inXmlMsg
	 * @param channelCode
	 * @param pwd
	 * @return String
	 * @throws Exception
	 */
	public static String formatXml(String inXmlMsg, String channelCode, String pwd) throws Exception {
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("channelcode", channelCode);
		inXmlMsg = DesUtilTo32.encode(inXmlMsg, pwd);
		jsonObject.put("xmlmsg", inXmlMsg);
		logger.info(jsonObject.toString());
		return jsonObject.toString();
	}

	/**
	 * 解密得到的结果(短信接口)
	 *
	 * @param resultInfo
	 * @param pwd
	 * @return String
	 * @throws Exception
	 */
	public static String parseXml(String resultInfo, String pwd) throws Exception {
		logger.info("resultInfo之前：" + resultInfo);
//		resultInfo = resultInfo.replace("\"", "\'");
		logger.info("resultInfo之后：" + resultInfo);
		JSONObject json = JSONObject.fromObject(resultInfo);
		String outXmlMsg = (String) json.get("resultinfo");
		outXmlMsg = DesUtilTo32.decode(outXmlMsg, pwd);
		return outXmlMsg;
	}

	/**
	 * 解密得到的结果
	 *
	 * @param resultInfo
	 * @param pwd
	 * @return
	 * @throws Exception
	 */
	public static String parseX(String resultInfo, String pwd) throws Exception {
		JSONObject json = JSONObject.fromObject(resultInfo);
		String outXmlMsg = (String) json.get("xmlmsg");
		outXmlMsg = DesUtilTo32.decode(outXmlMsg, pwd);
		return outXmlMsg;
	}


}
