package org.bench4q.recorder.httpcapture;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.swing.JOptionPane;

import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;

public class HttpTestCase {
	private Config config = Config.getConfig();
	protected HttpMethod method = null;
	protected HttpClient client = new HttpClient();
	protected String data;
	private boolean followRedirects = false;
	private String charset;

	public void setCharset(String cs) {
		this.charset = cs;
	}

	public HttpTestCase(String name) {
		Config.ProxySettings proxy = this.config.getProxySettings();
		if (proxy != null) {
			HostConfiguration hc = this.client.getHostConfiguration();
			hc.setProxy(proxy.host, proxy.port);
		}
	}

	public void Run() throws Throwable {
	}

	public HttpMethod getMethod() {
		return this.method;
	}

	private void cleanupMethod() {
		if (this.method != null) {
			this.method.releaseConnection();
			this.method = null;
		}
	}

	public void get(String url) throws IOException {
		get(url, null);
	}

	public void get(String url, Object[] args) throws IOException {
		cleanupMethod();

		this.method = new GetMethod(url);

		if (args != null) {
			this.method.setQueryString(paramsToNV(args));
		}

		this.method.setFollowRedirects(this.followRedirects);
		this.client.executeMethod(this.method);
	}

	public void post(String url) throws IOException {
		post(url, null);
	}

	public void post(String url, Object[] args) throws IOException {
		cleanupMethod();
		PostMethod post = new PostMethod(url);

		if (this.charset != null) {
			post.setRequestHeader("Content-Type",
					"application/x-www-form-urlencoded; charset="
							+ this.charset);
		}

		if (args != null) {
			post.setRequestBody(paramsToNV(args));
		}

		this.method = post;
		this.method.setFollowRedirects(this.followRedirects);
		this.client.executeMethod(this.method);
	}

	public void postMultiPart(String url, String data, int contLen)
			throws IOException {
		postMultiPart(url, data, contLen, null);
	}

	public void postMultiPart(String url, String data, int contLen,
			Object[] args) throws IOException {
		cleanupMethod();

		PostMethod multipartPostMethod = new PostMethod(url);

		multipartPostMethod.addParameter("data", data);
		if (args != null) {
			multipartPostMethod.setQueryString(paramsToNV(args));
		}

		this.method = multipartPostMethod;
		this.method.setFollowRedirects(this.followRedirects);
		this.client.executeMethod(this.method);
	}

	public NameValuePair[] paramsToNV(Object[] params) {
		NameValuePair[] res = new NameValuePair[params.length];
		for (int i = 0; i < params.length; ++i) {
			Object param = params[i];
			// if (param instanceof PyTuple) {
			// PyTuple pyParam = (PyTuple) param;
			// res[i] = new NameValuePair(pyParam.__getitem__(0).toString(),
			// pyParam.__getitem__(1).toString());
			// } else
			if (param instanceof NameValuePair) {
				res[i] = ((NameValuePair) param);
			}
		}
		return res;
	}

	public String urlDecode(String s) {
		return staticUrlDecode(s);
	}

	public static String staticUrlDecode(String s) {
		String sUrl = "";
		ByteArrayOutputStream out = new ByteArrayOutputStream(s.length());
		for (int count = 0; count < s.length(); ++count)
			if (s.charAt(count) == '%') {
				++count;
				if (count < s.length()) {
					int a = Character.digit(s.charAt(count++), 16);
					a <<= 4;
					int b = Character.digit(s.charAt(count), 16);

					if ((a + b == 39) || (a + b == 132))
						out.write(92);
					out.write(a + b);
				} else {
					out.write(37);
				}
			} else if (s.charAt(count) == '+') {
				out.write(32);
			} else {
				sUrl += s.charAt(count);
				out.write(s.charAt(count));
			}
		System.out.println(sUrl);
		return out.toString();
	}

	protected void responseOK() throws URIException {
	}

	protected boolean responseContainsURI(String uri) throws URIException {
		return ((this.method != null) && (this.method.getURI().getPath()
				.indexOf(uri) != -1));
	}

	protected boolean responseContains(String text) {
		try {
			if ((this.method == null)
					|| (this.method.getResponseBody() == null))
				return false;

			this.data = this.method.getResponseBodyAsString();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return (this.data.indexOf(text) != -1);
	}

	protected void printResponse() {
		try {
			System.err.println(new String(this.method.getResponseBody()));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public String getResponse() throws IOException {
		return this.method.getResponseBodyAsString();
	}

	public byte[] getResponseAsBytes() throws IOException {
		return this.method.getResponseBody();
	}

	public int getResponseCode() {
		return getMethod().getStatusCode();
	}

	// public PyDictionary getResponseHeader() {
	// PyDictionary dict = new PyDictionary();
	// Header[] headers = this.method.getResponseHeaders();
	//
	// for (int i = 0; i < headers.length; ++i)
	// dict.__setitem__(new PyString(headers[i].getName()), new PyString(
	// headers[i].getValue()));
	// return dict;
	// }

	public String getScriptArg() {
		return this.config.getScriptArg();
	}

	public boolean userConfirm(String msg) {
		int rc = JOptionPane.showConfirmDialog(null, msg, "HttpCapture", 2);
		return (rc == 0);
	}

	public String userInput(String msg) {
		return JOptionPane.showInputDialog(null, msg, "HttpCapture", 3);
	}

	public String getStrutsToken() throws IOException {
		String responseString = new String(
				this.method.getResponseBodyAsString());

		String strutsToken = null;

		int tokenIDIndex = responseString.toLowerCase().indexOf(
				"org.apache.struts.taglib.html.TOKEN".toLowerCase());
		int nextValue = responseString.toLowerCase().indexOf(
				"value=\"".toLowerCase(), tokenIDIndex);

		strutsToken = responseString.substring(nextValue + "value=\"".length(),
				nextValue + "value=\"".length() + 32);
		return strutsToken;
	}
}
