package org.springblade.openinterface.dianxin.util;




import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
/**
 * @author lidexi
 * @date 2021/6/23 18:00
 */

public class HttpUtil {

	private static final Charset UTF_8 = Charset.forName("utf-8");

	private static final int DEFAULT_CONNECT_TIMEOUT = 1000;

	private static final int DEFAULT_READ_TIMEOUT = 6000;

	private HttpURLConnection conn;

	private String url;

	private HashMap<String, String> headers = new HashMap<String, String>();

	private HashMap<String, String> param = new HashMap<String, String>();

	private OutputStream out;

	private InputStream in;

	private boolean error = false;

	private String errMsg = "";

	private int connectTimeout = DEFAULT_CONNECT_TIMEOUT;

	private int readTimeout = DEFAULT_READ_TIMEOUT;

	public HttpUtil(String url) {
		this.url = url;
	}

	public HttpUtil() {
	}

	public HttpUtil url(String url) {
		this.url = url;
		return this;
	}

	public HttpUtil postForm(Object param) {
		this.header("Content-Type", "application/x-www-form-urlencoded");
		this.post(FormString.asForm(param));
		return this;
	}

	public HttpUtil get() {
		try {
			StringBuilder sb = new StringBuilder();
			if (param != null && param.size() > 0) {
				boolean isFirst = true;
				for (Map.Entry<String, String> e : param.entrySet()) {
					if (isFirst) {
						isFirst = false;
					} else {
						sb.append("&");
					}
					sb.append(e.getKey()).append("=").append(e.getValue());
				}
				if (url.indexOf('?') > -1) {
					url += "&" + sb;
				} else {
					url += "?" + sb;
				}
			}

			open("GET");
			conn.setDoOutput(false);
		} catch (Exception e) {
			error = true;
			errMsg = "can not access :" + url + " msg:" + e.getMessage();
			e.printStackTrace();
		}
		return this;
	}

	public HttpUtil post() {
		post(param);
		return this;
	}

	public HttpUtil post(File o) {

		return this;
	}

	public HttpUtil post(Object o) {
		if (o != null)
			post(JsonString.asJsonString(o));
		return this;
	}

	public HttpUtil post(String o) {
		if (o != null)
			post(o.getBytes(UTF_8));
		return this;
	}

	public HttpUtil post(byte[] bytes) {
		if (bytes != null)
			try {
				if (isHTTPS(url)) {
					HttpsURLConnection.setDefaultHostnameVerifier(new NullHostNameVerifier());
					SSLContext sc = SSLContext.getInstance("TLS");
					sc.init(null, trustAllCerts, new SecureRandom());
					HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
				}
				URL uri = new URL(url);
				conn = (HttpURLConnection) uri.openConnection();
				conn.setDoOutput(true);
				conn.setUseCaches(false);
				conn.setConnectTimeout(10000);
				conn.setRequestMethod("POST");
				setHeaders(conn, this.headers);
				if (headers == null || !headers.containsKey("Content-Type"))
					conn.setRequestProperty("Content-Type", "text/json");
				conn.connect();
				OutputStream out = conn.getOutputStream();
				out.write(bytes);
				out.close();
				int status = conn.getResponseCode();
			} catch (Exception e) {
				error = true;
				errMsg = "can not access :" + url + " nmsg:" + e.getMessage();
				e.printStackTrace();
			}
		return this;
	}

	private static void setHeaders(HttpURLConnection conn, Map<String, String> header) {
		if (header == null)
			return;
		for (Object o : header.entrySet()) {
			Entry<String, String> entry = (Entry<String, String>) o;
			conn.setRequestProperty(entry.getKey(), entry.getValue());
		}
	}

	public HttpUtil param(Map param) {
		this.param.putAll(param);
		return this;
	}

	public HttpUtil header(Map param) {
		headers.putAll(param);
		return this;
	}

	public HttpUtil param(String k, String v) {
		param.put(k, v);
		return this;
	}

	public HttpUtil header(String k, String v) {
		headers.put(k, v);
		return this;
	}

	public String asString() {
		return asString(UTF_8);
	}

	public String asString(Charset charset) {
		if (this.error)
			return "{code:\"-1\",msg:\"" + errMsg + "\"}";
		return new String(asBytes(), charset);
	}

	public byte[] asBytes() {
		try {
			in = conn.getInputStream();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			byte[] b = new byte[1024];
			int len = 0;
			while ((len = in.read(b)) > 0) {
				bos.write(b, 0, len);
			}
			in.close();
			in = null;
			if (out != null) {
				out.close();
			}
			out = null;
			byte[] bs = bos.toByteArray();
			bos.close();
			return bs;
		} catch (IOException e) {
			error = true;
			errMsg = e.getMessage();
			e.printStackTrace();
		}
		return new byte[0];
	}

	private void open(String method) throws Exception {
		URL httpurl = null;
		if (isHTTPS(url)) {
			HttpsURLConnection.setDefaultHostnameVerifier(new NullHostNameVerifier());
			SSLContext sc = SSLContext.getInstance("TLS");
			sc.init(null, trustAllCerts, new SecureRandom());
			HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
		}
		httpurl = new URL(url);

		conn = (HttpURLConnection) httpurl.openConnection();
		conn.setRequestMethod(method);// POST GET PUT DELETE
		conn.setConnectTimeout(connectTimeout);
		conn.setReadTimeout(readTimeout);
		if (headers != null && headers.size() > 0) {
			for (Map.Entry<String, String> e : headers.entrySet()) {
				conn.setRequestProperty(e.getKey(), e.getValue());
			}
		}
	}

	public String getResponseHeader(String k) {
		return conn.getHeaderField(k);
	}

	public boolean isHTTPS(String url) {
		if (url.toLowerCase().startsWith("https"))
			return true;
		return false;
	}

	public HttpUtil setConnectTimeout(int timeout) {
		connectTimeout = timeout;
		return this;
	}

	public HttpUtil setReadTimeout(int timeout) {
		readTimeout = timeout;
		return this;
	}

	static TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
	} };

	public class NullHostNameVerifier implements HostnameVerifier {

		public boolean verify(String arg0, SSLSession arg1) {
			return true;
		}
	}
}
