package de.ugoe.cs.quest.web.data;

import java.util.ArrayList;
import java.util.List;

import de.ugoe.cs.quest.eventcore.IReplayable;

/**
 * <p>
 * Contains all information related to a web request, i.e., the path, the POST
 * variables and the GET variables. The generated replay are for the command
 * line tool {@code curl}. The requests do not contain correct values for the
 * POST and GET request. Instead, only the parameters that are part of the
 * requests are added and the values of the parameters are
 * DATA_$PARAMNAME$_DATA, where $PARAMNAME$ is the upper case string of the
 * parameter name. This allows test data generators to insert concrete values,
 * as EventBench does not include a test data generator for web software.
 * </p>
 * 
 * @author Steffen Herbold
 * @version 1.0
 */
public class WebRequest implements IReplayable {

	/**
	 * <p>
	 * Id for object serialization.
	 * </p>
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * <p>
	 * POST variables of the web request.
	 * </p>
	 */
	List<String> postVars;

	/**
	 * <p>
	 * GET variables of the web request.
	 * </p>
	 */
	List<String> getVars;

	/**
	 * <p>
	 * URI of the web request.
	 * </p>
	 */
	String targetUri;

	/**
	 * <p>
	 * URL of the server.
	 * </p>
	 */
	String serverUrl;

	/**
	 * <p>
	 * Constructor. Creates a new WebRequest.
	 * </p>
	 * 
	 * @param uri
	 *            URI of the request
	 * @param postVars
	 *            POST variables of the request
	 * @param getVars
	 *            GET variables of the request
	 */
	public WebRequest(String url, String uri, List<String> postVars,
			List<String> getVars) {
		serverUrl = url;
		targetUri = uri;
		this.postVars = new ArrayList<String>(postVars); // defensive copy
		this.getVars = new ArrayList<String>(getVars);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see de.ugoe.cs.quest.eventcore.IReplayable#getReplay()
	 */
	@Override
	public String getReplay() {
		StringBuilder builder = new StringBuilder();
		builder.append("curl");
		if (!postVars.isEmpty()) {
			boolean isFirstPost = true;
			for (String postVar : postVars) {
				if (isFirstPost) {
					builder.append(" --data \"");
					isFirstPost = false;
				} else {
					builder.append('&');
				}
				builder.append(postVar + "=DATA_" + postVar.toUpperCase()
						+ "_DATA");
			}
			builder.append('\"');
		}
		builder.append(' ');
		if (serverUrl != null) {
			builder.append(serverUrl);
		}
		builder.append(targetUri);
		if (!getVars.isEmpty()) {
			boolean isFirstGet = true;
			for (String getVar : getVars) {
				if (isFirstGet) {
					builder.append('?');
					isFirstGet = false;
				} else {
					builder.append('&');
				}
				builder.append(getVar + "=DATA_" + getVar.toUpperCase()
						+ "_DATA");
			}
		}
		return builder.toString();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see de.ugoe.cs.quest.eventcore.IReplayable#getTarget()
	 */
	@Override
	public String getTarget() {
		return targetUri;
	}

	/**
	 * <p>
	 * Two {@link WebRequest}s are equal, if their {@link #targetUri},
	 * {@link #postVars}, and {@link #getVars} are equal.
	 * </p>
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object other) {
		if (this == other) {
			return true;
		}
		if (other instanceof WebRequest) {
			return targetUri.equals(((WebRequest) other).targetUri)
					&& postVars.equals(((WebRequest) other).postVars)
					&& getVars.equals(((WebRequest) other).getVars);
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		int multiplier = 17;
		int hash = 42;

		hash = multiplier * hash + targetUri.hashCode();
		hash = multiplier * hash + postVars.hashCode();
		hash = multiplier * hash + getVars.hashCode();

		return hash;
	}

}
