package util;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HttpClientUtil {
	/** 
     * 日志处理类 
     */  
    private static final Log log = LogFactory.getLog(HttpClientUtil.class);  
  
    // 读取超时  
    private final static int SOCKET_TIMEOUT = 60000;  
    // 连接超时  
    private final static int CONNECTION_TIMEOUT = 60000;  
    // 每个HOST的最大连接数量  
    private final static int MAX_CONN_PRE_HOST = 20;  
    // 连接池的最大连接数  
    private final static int MAX_CONN = 100;  
    // 连接池  
    private final static HttpConnectionManager httpConnectionManager;  
  
    static {  
        httpConnectionManager = new MultiThreadedHttpConnectionManager();  
        HttpConnectionManagerParams params = httpConnectionManager.getParams();  
        params.setConnectionTimeout(CONNECTION_TIMEOUT);  
        params.setSoTimeout(SOCKET_TIMEOUT);  
        params.setDefaultMaxConnectionsPerHost(MAX_CONN_PRE_HOST);  
        params.setMaxTotalConnections(MAX_CONN);  
    }  
  
    /**
     * Http get请求，获取结果.
     * @param url
     * @param ip
     * @return
     */
	public static String doHttpGetRequest(String url, String ip) {
		HttpClient httpClient = new HttpClient(httpConnectionManager);
		resetRequestHeader(httpClient, ip);
		HttpMethod method = new GetMethod(url);
		String response = null;
		try {
			httpClient.executeMethod(method);
			if (method.getStatusCode() == HttpStatus.SC_OK) {
				response = method.getResponseBodyAsString();
			}
		} catch (IOException e) {
			log.error("执行HTTP Get请求" + url + "时，发生异常！", e);
		} finally {
			method.releaseConnection();
		}
		return response;
	}  
	
	public static String doHttpGetRequest4Mobile(String url, String ip) {
		HttpClient httpClient = new HttpClient(httpConnectionManager);
		resetRequestHeader4Mobile(httpClient, ip);
		HttpMethod method = new GetMethod(url);
		String response = null;
		try {
			httpClient.executeMethod(method);
			if (method.getStatusCode() == HttpStatus.SC_OK) {
				response = method.getResponseBodyAsString();
			}
		} catch (IOException e) {
			log.error("执行HTTP Get请求" + url + "时，发生异常！", e);
		} finally {
			method.releaseConnection();
		}
		return response;
	}  
	
	
	/**
     * Http post请求，获取结果.
     * @param url
     * @param ip
     * @return
     */
	public static String doHttpPostRequest(String url, String ip, Map<String, String> params) {
		long start = System.currentTimeMillis();
		HttpClient httpClient = new HttpClient(httpConnectionManager);
		httpClient.getHttpConnectionManager().getParams()
		.setConnectionTimeout(300000);
		httpClient.getHttpConnectionManager().getParams().setSoTimeout(300000);
		resetRequestHeader(httpClient, ip);
		PostMethod method = new PostMethod(url);
		List<NameValuePair> list = new ArrayList<NameValuePair>();
		
		for (String key : params.keySet()) {
			NameValuePair pair = new NameValuePair(key, params.get(key));
			list.add(pair);
		}
		method.setRequestBody(list.toArray(new NameValuePair[list.size()]));
		String response = null;
		try {
			int status = httpClient.executeMethod(method);
			response = method.getResponseBodyAsString();
		} catch (IOException e) {
			log.error("执行HTTP Post请求" + url + "时，发生异常！", e);
		} finally {
			method.releaseConnection();
		}
		long end = System.currentTimeMillis();
		log.debug("---------------http's time to get data from report-------------------");
		log.debug(start-end + "ms");
		log.debug("---------------------------------------------------------------------");
		return response;
	}

	/**
	 * Http post请求，获取结果.
	 * @param url
	 * @param ip
	 * @return
	 */
	public static String doHttpPostRequest(String url, String ip) {
		long start = System.currentTimeMillis();
		HttpClient httpClient = new HttpClient(httpConnectionManager);
		httpClient.getHttpConnectionManager().getParams()
				.setConnectionTimeout(300000);
		httpClient.getHttpConnectionManager().getParams().setSoTimeout(300000);
		resetRequestHeader(httpClient, ip);
		PostMethod method = new PostMethod(url);
		List<NameValuePair> list = new ArrayList<NameValuePair>();

		String response = null;
		try {
			int status = httpClient.executeMethod(method);
			response = method.getResponseBodyAsString();
		} catch (IOException e) {
			log.error("执行HTTP Post请求" + url + "时，发生异常！", e);
		} finally {
			method.releaseConnection();
		}
		long end = System.currentTimeMillis();
		log.debug("---------------http's time to get data from report-------------------");
		log.debug(start-end + "ms");
		log.debug("---------------------------------------------------------------------");
		return response;
	}

	/**
     * 设置一下返回错误的通用提示,可以自定义格式. 
     * @param reason 
     * @return 
     */  
    public static String returnError(String reason) {  
        StringBuffer buffer = new StringBuffer();  
        buffer.append("<?xml version=\"1.0\" encoding=\"GBK\"?>");  
        buffer.append("<Response>");  
        buffer.append("<Success>false</Success>");  
        buffer.append("<reason>");  
        buffer.append(reason);  
        buffer.append("</reason>");  
        buffer.append("</Response>");  
        return buffer.toString();  
    }  
  
      
    public final static String REQUEST_HEADER = "x-forwarded-for";  
    /** 
     * 将客户IP写入请求头 
     * 这个设置可以伪装IP请求,注意使用 
     * @param client 
     * @param ip 
     * @return 
     */  
    public static void resetRequestHeader(HttpClient client, String ip) {  
        List<Header> headers = new ArrayList<Header>();  
        headers.add(new Header(REQUEST_HEADER, ip));  
        client.getHostConfiguration().getParams().setParameter(  
                "http.default-headers", headers);  
        client.getHostConfiguration().getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"utf-8");
    }
    
    public static void resetRequestHeader4Mobile(HttpClient client, String ip) {  
        List<Header> headers = new ArrayList<Header>();  
        headers.add(new Header(REQUEST_HEADER, ip));  
        client.getHostConfiguration().getParams().setParameter(  
                "http.default-headers", headers);  
        client.getHostConfiguration().getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"GBK");
    }
    
    public static boolean httpAWS(Map<String, String> args, String ip, String surl, String url) throws Exception {
		String response = "";
		for (int i=0; i<3; i++) {
			response = HttpClientUtil.doHttpPostRequest(url, ip, args);
			if (!StringUtil.isEmpty(response)) {
				ObjectMapper objectMapper = new ObjectMapper();
				Map res = objectMapper.readValue(response, Map.class);
				if (res.containsKey("result") && res.get("result").equals("true")) {
					log.info("success to "+args.get("method")+" AWS redis campaigninfo by surl:" + surl);
					return true;
				}
			}
		}
		
		if (StringUtil.isEmpty(response)) {
			MailUtils.sendSimpleEmail("Fail to "+args.get("method")+" AWS redis campaigninfo by surl:" + surl, new ObjectMapper().writeValueAsString(args), Constant.mlist);
			return false;
		}
		return false;
	}

	public static void resetRequestHeader(HttpClient client, String ip, String cookie) {
		List<Header> headers = new ArrayList<Header>();
		headers.add(new Header(REQUEST_HEADER, ip));
		headers.add(new Header("Cookie", cookie));
		client.getHostConfiguration().getParams().setParameter(
				"http.default-headers", headers);
//        client.getHostConfiguration().getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"utf-8");
	}

	public static ByteArrayOutputStream doHttpGetStreamRequest(String url, String ip, String cookie)
	{
		HttpClient httpClient = new HttpClient(httpConnectionManager);
		resetRequestHeader(httpClient, ip, cookie);
		HttpMethod method = new GetMethod(url);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		InputStream response = null;
		try {
			httpClient.executeMethod(method);
			if (method.getStatusCode() == HttpStatus.SC_OK) {
				response = method.getResponseBodyAsStream();
				byte[] buffer = new byte[1024];
				int len;
				while ((len = response.read(buffer)) > -1 ) {
					baos.write(buffer, 0, len);
				}
				baos.flush();
			}
		} catch (IOException e) {
			log.error("执行HTTP Get请求" + url + "时，发生异常！", e);
		} finally {
			method.releaseConnection();
		}
		return baos;
	}

	public static Map<String,Object> doHttpGetHeaderAndBody(String url, String ip, String cookie)
	{
		HttpClient httpClient = new HttpClient(httpConnectionManager);
		resetRequestHeader(httpClient, ip, cookie);
		HttpMethod method = new GetMethod(url);
		ByteArrayOutputStream baosHeader = new ByteArrayOutputStream();
		ByteArrayOutputStream baosBody = new ByteArrayOutputStream();
		InputStream responseBody = null;
		InputStream responseHeader = null;
		Map<String,Object> result = new HashMap<>();
		try {
			httpClient.executeMethod(method);
			if (method.getStatusCode() == HttpStatus.SC_OK) {
				responseBody = method.getResponseBodyAsStream();
				byte[] buffer = new byte[1024];
				int len;
				while ((len = responseBody.read(buffer)) > -1 ) {
					baosBody.write(buffer, 0, len);
				}
				baosBody.flush();
				result.put("body",baosBody);


				Header headers = method.getResponseHeader("Set-Cookie");
				String value = headers.getValue();
				result.put("cookie", value);

			}
		} catch (IOException e) {
			log.error("执行HTTP Get请求" + url + "时，发生异常！", e);
		} finally {
			method.releaseConnection();
		}
		return result;
	}

//	public static String doHttpPostRequest(String url, String ip, Map<String, String> params, String cookie) {
//		long start = System.currentTimeMillis();
//		HttpClient httpClient = new HttpClient(httpConnectionManager);
//		httpClient.getHttpConnectionManager().getParams()
//				.setConnectionTimeout(300000);
//		httpClient.getHttpConnectionManager().getParams().setSoTimeout(300000);
//		resetRequestHeader(httpClient, ip, cookie);
//		PostMethod method = new PostMethod(url);
//		List<NameValuePair> list = new ArrayList<NameValuePair>();
//
//		for (String key : params.keySet()) {
//			NameValuePair pair = new NameValuePair(key, params.get(key));
//			list.add(pair);
//		}
//		method.setRequestBody(list.toArray(new NameValuePair[list.size()]));
//		String response = null;
//		try {
//			int status = httpClient.executeMethod(method);
//			response = method.getResponseBodyAsString();
//		} catch (IOException e) {
//			log.error("执行HTTP Post请求" + url + "时，发生异常！", e);
//		} finally {
//			method.releaseConnection();
//		}
//		long end = System.currentTimeMillis();
//		log.debug("---------------http's time to get data from report-------------------");
//		log.debug(start-end + "ms");
//		log.debug("---------------------------------------------------------------------");
//		return response;
//	}

	public static String doHttpPostRequest(String url, String ip, Map<String, String> params, String code)
	{
		return doHttpPostRequest(url, ip, params, "ISO-8859-1", code);
	}

	/**
	 * Http post请求，获取结果.
	 *
	 * @param url
	 * @param ip
	 * @return
	 */
	public static String doHttpPostRequest(String url, String ip, Map<String, String> params, String readCharsetName, String writeCharsetName)
	{
		HttpClient httpClient = new HttpClient(httpConnectionManager);
		httpClient.getHttpConnectionManager().getParams()
				.setConnectionTimeout(300000);
		httpClient.getHttpConnectionManager().getParams().setSoTimeout(300000);
		resetRequestHeader(httpClient, ip);
		PostMethod method = new PostMethod(url);
		List<NameValuePair> list = new ArrayList<NameValuePair>();

		for (String key : params.keySet()) {
			NameValuePair pair = new NameValuePair(key, params.get(key));
			list.add(pair);
		}
		NameValuePair[] body = new NameValuePair[list.size()];
		body = list.toArray(body);
		method.setRequestBody(body);
		return executeMethod(httpClient, method, readCharsetName, writeCharsetName);
	}
	private static String executeMethod(HttpClient httpClient, HttpMethod method, String readCharsetName, String writeCharsetName)
	{
		String response = null;
		try {
			httpClient.executeMethod(method);
		}
		catch (IOException e) {
//			try {
//				logger.error("执行HTTP请求" + method.getURI().toString() + "时，发生异常！", e);
//			}
//			catch (URIException e1) {
//				logger.error("URIException", e1);
//			}
		}
		finally {
			if (method.getStatusCode() == HttpStatus.SC_OK) {
				StringBuffer stringBuffer = new StringBuffer();
				try {
					BufferedReader reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream(), readCharsetName));
					String str = "";

					while ((str = reader.readLine()) != null) {
						stringBuffer.append(new String(str.getBytes(readCharsetName), writeCharsetName));
					}
				}
				catch (IOException e) {
//					try {
//						//logger.error("执行HTTP响应结果" + method.getURI().toString() + "时，发生异常！", e);
//					}
//					catch (URIException e1) {
//						//logger.error("URIException", e1);
//					}
				}
				response = stringBuffer.toString();
			}
			method.releaseConnection();
		}
		return response;
	}
}
