package de.ugoe.cs.quest.plugin.php.eventcore;

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

import de.ugoe.cs.quest.IReplayDecorator;
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();
    }

    /**
     * <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;
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.quest.eventcore.IReplayable#getDecorator()
     */
    @Override
    public IReplayDecorator getDecorator() {
        return null;
    }

}
