package com.cku.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;

public class HttpClientUtil 
{
	private static HttpClient _createClient()
	{
		HttpConnectionManagerParams p = new HttpConnectionManagerParams();
		HttpConnectionManager mgr = new SimpleHttpConnectionManager();
		p.setConnectionTimeout(2000);
		mgr.setParams(p);
		HttpClient c = new HttpClient();
		c.setHttpConnectionManager(mgr);
		return c;
	}
	
	public static HttpResult put(HttpClient client, String actionURI, String type, String content) throws HttpException, IOException
	{
		if (client == null)
		{
			client = _createClient();
		}
		PutMethod method = new PutMethod(actionURI);
		method.setRequestHeader("Connection", "close");

		try
		{		
			StringRequestEntity sre = new StringRequestEntity(content, type, "UTF-8");
			method.setRequestEntity(sre);
			client.executeMethod(method);
			return new HttpResult(method.getStatusCode(), method.getStatusText(), _getStringBody(method));
		}
		finally
		{
			method.releaseConnection();
		}
	}

	public static HttpResult postFile(HttpClient client, String actionURI, String filePath) throws HttpException, IOException
	{
		if (client == null)
		{
			client = _createClient();
		}
		PostMethod method = new PostMethod(actionURI);
		method.setRequestHeader("Connection", "close");
		
		try
		{
			File file = new File(filePath);
			FilePart fp = new FilePart(file.getName(), file);
			Part[] parts = { fp };
			MultipartRequestEntity sre = new MultipartRequestEntity(parts, method.getParams());
			method.setRequestEntity(sre);
			client.executeMethod(method);
		
			return new HttpResult(method.getStatusCode(), method.getStatusText(), _getStringBody(method));
		}
		finally
		{
			method.releaseConnection();
		}
	}
	
	public static HttpResult post(HttpClient client, String actionURI, String type, String content) throws HttpException, IOException
	{
		if (client == null)
		{
			client = _createClient();
		}
		PostMethod method = new PostMethod(actionURI);
		method.setRequestHeader("Connection", "close");
		
		try
		{
			StringRequestEntity sre = new StringRequestEntity(content, type, "UTF-8");
			method.setRequestEntity(sre);
			client.executeMethod(method);
		
			return new HttpResult(method.getStatusCode(), method.getStatusText(), _getStringBody(method));
		}
		finally
		{
			method.releaseConnection();
		}
	}
	
	public static HttpResult post(HttpClient client, String actionURI, Map<String, String> params) throws HttpException, IOException
	{
		if (client == null)
		{
			client = _createClient();
		}
		PostMethod method = new PostMethod(actionURI);
		method.setRequestHeader("Connection", "close");

		try
		{
			method.setRequestHeader("Connection", "close");
			if (params != null && !params.isEmpty())
			{
				List<NameValuePair> paramList = new ArrayList<NameValuePair>();
				for(Iterator<String> ite = params.keySet().iterator(); ite.hasNext() ;)
				{
					String key = ite.next();
					NameValuePair nvp = new NameValuePair(key, params.get(key));
					paramList.add(nvp);
				}
				method.setRequestBody((NameValuePair[]) paramList.toArray());
			}
			client.executeMethod(method); 
			return new HttpResult(method.getStatusCode(), method.getStatusText(), _getStringBody(method));
		}
		finally
		{
			method.releaseConnection();
		}
	}

	private static String _getParamString(Map<String, String> params) throws UnsupportedEncodingException
	{
		StringBuilder sb = new StringBuilder();
		if (params != null)
		{
			boolean first = true;
			for (String key : params.keySet())
			{
				String value = URLEncoder.encode(params.get(key), "utf-8");
				if (first)
				{
					sb.append("?").append(key).append("=").append(value);
					first = false;
				}
				else
				{
					sb.append("&").append(key).append("=").append(value);		
				}
			}
		}
		
		return sb.toString();
	}

	public static HttpResult delete(HttpClient client, String actionURI, Map<String, String> params) throws HttpException, IOException
	{
		if (client == null)
		{
			client = _createClient();
		}
		DeleteMethod method = new DeleteMethod(actionURI + _getParamString(params));
		method.setRequestHeader("Connection", "close");
		try
		{	
			client.executeMethod(method); 
			return new HttpResult(method.getStatusCode(), method.getStatusText(), _getStringBody(method));
		}
		finally
		{
			method.releaseConnection();
		}
	}
	
	private static String _getStringBody(HttpMethodBase method) throws IOException
	{
		InputStream is = method.getResponseBodyAsStream();
		try
		{
			BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
			StringBuilder resBuffer = new StringBuilder();
			String resTemp = "";
			while((resTemp = br.readLine()) != null){
				resBuffer.append(resTemp);
			}
			String response = resBuffer.toString();
			return response;
		}
		finally
		{
			try { is.close(); } catch (Exception e) {}
		}
	}
	
	public static HttpResult get(HttpClient client, String actionURI, Map<String, String> params) throws HttpException, IOException
	{		
		if (client == null)
		{
			client = _createClient();
		}
		GetMethod method = new GetMethod(actionURI + _getParamString(params));
		method.setRequestHeader("Connection", "close");
		try
		{
			client.executeMethod(method);
			
			return new HttpResult(method.getStatusCode(), method.getStatusText(), _getStringBody(method));
		}
		finally
		{
			method.releaseConnection();
		}
	}
}
