import java.io.*;
import java.net.*;
import java.util.*;

/**
 * An encapsulation of an HTTP request
 *
 * This version:
 *
 *     Handles headers
 *     Handles query string parameters
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 0.1
 */
public class HttpRequest
{
    private int            contentLength;    
    private NameValueMap   headers, queryParameters;
    private String         method, queryString, version;
    private URI            uri;


    /**
     * Default Constructor
     */
    public HttpRequest()
    {
       method          = null;       
       queryString     = null;       
       version         = null;
    }

    /**
     * Returns the name of the HTTP method with which this request was made, 
     * (for example, GET, POST, or PUT)
     *
     * @return  The method
     */
    public String getMethod()
    {
       return method;
    }

    /**
     * Returns the part of this request's URI from the protocol name 
     * up to the query string in the first line of the HTTP request
     *
     * @return   The URI
     */
    public String getRequestURI()
    {
       String     path;
       
       path = uri.getPath();
       if ((path == null) || path.equals("")) return "index.html";
       else                                   return path;
    }

    /**
     * Read this request
     *
     * @param in   The HttpInputStream to read from
     */
    public void read(HttpInputStream in) throws IndexOutOfBoundsException,
                                                IOException, URISyntaxException
    {
       InputStream          tis;       
       String               line, request, token, value;
       String[]             pair, tokens;


       line = in.readHttpLine();

       tokens = line.split("\\s");

       method  = tokens[0];
       request = tokens[1];
       if (tokens.length > 2) version = tokens[2];
       else                   version = "HTTP/0.9";

       // Parse the URI
       uri = new URI(request);

       // Get the decoded query string
       queryString = uri.getQuery();

       // Process the query string
       queryParameters = NameValueMap.createNameValueMap();
       if (queryString != null) queryParameters.putPairs(queryString,"&","=");
          
       // Process the headers
       headers = NameValueMap.createNameValueMap();
       headers.putPairs(in, ":");

       // Get the content length
       token = headers.getValue("Content-Length");
       try 
       {
           contentLength = Integer.parseInt(token.trim());
       } 
       catch (Exception e) 
       {
          contentLength = -1;
       }
    }

    /**
     * Returns a String representation of this Object
     *
     * @return   The String representation
     */
    public String toString()
    {
       Iterator<String>  i;
       String            name, s, value;

       s  = "Method: \n\t" + getMethod() + "\n";
       s += "URI: \n\t"    + getRequestURI()+"\n";

       s += "Parameters:\n"+ queryString + "\n";

       s += "Headers:\n";
       i = headers.getNames();
       while (i.hasNext()) 
       {
          name  = i.next();
          value = headers.getValue(name);
          s += "\t" + name + "\t" + value + "\n";
       }

       return s;
    }
}
