package com.winsun.tenpay.util;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

public class HttpUtil {
	private static HttpClient httpClient = null;
	protected static final Logger log = Logger.getLogger(HttpUtil.class);

	static {
		MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
		httpClient = new HttpClient(connectionManager);

		httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(10000);
		httpClient.getHttpConnectionManager().getParams().setSoTimeout(20000);
		httpClient.setHttpConnectionFactoryTimeout(10000L);
	}

	/**
	 * 访问https的网站
	 * 
	 * @param httpclient
	 */
	private static void enableSSL(DefaultHttpClient httpclient) {
		// 调用ssl
		try {
			SSLContext sslcontext = SSLContext.getInstance("TLS");
			sslcontext.init(null, new TrustManager[] { truseAllManager }, null);
			SSLSocketFactory sf = new SSLSocketFactory(sslcontext);
			sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
			Scheme https = new Scheme("https", sf, 443);
			httpclient.getConnectionManager().getSchemeRegistry().register(https);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static TrustManager truseAllManager = new X509TrustManager() {

		public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
				throws CertificateException {
			// TODO Auto-generated method stub

		}

		public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
				throws CertificateException {
			// TODO Auto-generated method stub

		}

		public java.security.cert.X509Certificate[] getAcceptedIssuers() {
			// TODO Auto-generated method stub
			return null;
		}

	};

	public static String doPostXml(String serverAddress, String xml) {

		/*
		 * //CerPath证书路径 String certPath =
		 * ConfigurationManager.AppSettings["certPath"].ToString(); //证书密码
		 * String password =
		 * ConfigurationManager.AppSettings["password"].ToString();
		 * X509Certificate cert = new
		 * System.Security.Cryptography.X509Certificates.X509Certificate2(
		 * certPath, password, X509KeyStorageFlags.MachineKeySet);
		 * 
		 * // 设置参数 request = WebRequest.Create(posturl) as HttpWebRequest;
		 */

		String searchResult = "";
		String url = serverAddress;
		log.info("url=" + url);
		PostMethod postMethod = new PostMethod(url);
		postMethod.addRequestHeader("Content-Type", "text/xml;charset=UTF-8");

		postMethod.setRequestBody(xml);
		BufferedInputStream ins = null;
		try {

			int statusCode = httpClient.executeMethod(postMethod);
			if (statusCode == 200) {
				ins = new BufferedInputStream(postMethod.getResponseBodyAsStream());
				byte[] resultBytes = readUrlStream(ins);
				if ((resultBytes != null) && (resultBytes.length > 0)) {
					searchResult = new String(resultBytes, "UTF-8");
					//log.info(searchResult);
				}
			}
		} catch (HttpException e) {
			log.error("HttpUtil doPost unexpected exception:" + e.toString());
		} catch (Exception e) {
			log.error("HttpUtil doPost unexpected exception:" + e.toString());
		} finally {
			postMethod.releaseConnection();
			try {
				if(null != ins)
					ins.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return searchResult;
	}

	public static String httpPost(String url, String data) throws Exception {
		Integer statusCode = -1;
		CloseableHttpClient client = HttpClients.createDefault();
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(20000).setConnectTimeout(20000).build();
		SSLConnectionSocketFactory sslsf = null;

		try {

			// 指定读取证书格式为PKCS12
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			// 读取本机存放的PKCS12证书文件
			URL certUrl = HttpUtil.class.getClassLoader().getResource("apiclient_cert.p12");
			File file = new File(certUrl.getFile());
			FileInputStream instream = new FileInputStream(file);
			try {
				// 指定PKCS12的密码(商户ID)
				
				System.out.println(ConstantUtil.PKCS12_PWD);
				keyStore.load(instream, ConstantUtil.PKCS12_PWD.toCharArray());

			} finally {
				instream.close();
			}
			SSLContext sslcontext = SSLContexts.custom()
					.loadKeyMaterial(keyStore, ConstantUtil.PKCS12_PWD.toCharArray()).build();

			sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" },
					null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

			client = HttpClients.custom().setSSLSocketFactory(sslsf).build();

			// 创建http请求(get方式)
			// HttpGet httpget = new
			// HttpGet("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers");
			// CloseableHttpResponse response = client.execute(httpget);
			// System.out.println("executing request" +
			// httpget.getRequestLine());
			// httpClient = (HttpClient) httpclient.getConnectionManager();
		} catch (FileNotFoundException e) {

			e.printStackTrace();

		} catch (KeyStoreException e1) {

			e1.printStackTrace();
		} catch (NoSuchAlgorithmException e) {

			e.printStackTrace();
		} catch (CertificateException e) {

			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		} catch (KeyManagementException e) {

			e.printStackTrace();
		} catch (UnrecoverableKeyException e) {

			e.printStackTrace();
		}finally {
			client.close();
		}

		HttpPost post = new HttpPost(url);
		post.setConfig(requestConfig);
		StringEntity entity = new StringEntity(data, "UTF-8");
		entity.setContentType("application/json;charset=UTF-8");
		post.setEntity(entity);
		post.setHeader("accept", "application/json");

		post.setHeader("Content-Type", "application/json;charset=UTF-8");
		CloseableHttpResponse response = client.execute(post);

		StringBuffer result = new StringBuffer();
		try {
			statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				throw new HttpException("Http Status is error: " + statusCode);
			} else {
				HttpEntity entityRsp = response.getEntity();
				BufferedReader rd = new BufferedReader(new InputStreamReader(entityRsp.getContent(), "UTF-8"));
				try {
					String tempLine = rd.readLine();
					while (tempLine != null) {
						result.append(tempLine);
						tempLine = rd.readLine();
					}
				} finally {
					rd.close();
					EntityUtils.consume(entityRsp);
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			response.close();
		}
		client.close();
		return result.toString();
	}

	private static byte[] readUrlStream(BufferedInputStream bufferedInputStream) throws IOException {
		ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
		byte[] buff = new byte[100];
		int rc = 0;
		while ((rc = bufferedInputStream.read(buff, 0, 100)) > 0) {
			swapStream.write(buff, 0, rc);
		}
		return swapStream.toByteArray();
	}
}
