package com.jpexs.proxy;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.StringBufferInputStream;
import java.io.SequenceInputStream;
import java.util.Hashtable;
import java.util.StringTokenizer;

public class Reply extends Message
{
    InputStream in = null;
    int statusCode = -1;

    public Reply()
    {
    }

    public Reply(InputStream in)
    {
	setContent(in);
    }

    public void setContent(InputStream in)
    {
	this.in = in;
    }

    public InputStream getContent()
    {
	return in;
    }
    
    void read() throws IOException
    {
	if (in != null)
	{
	    read(in);
	}
    }
    
    void read(InputStream in) throws IOException
    {
	statusLine = readLine(in);
	if (statusLine == null || statusLine.length() == 0)
	{
	    throw new IOException("Missing HTTP status line");
	}

	/* Look for HTTP/0.9 */
	if (!statusLine.startsWith("HTTP"))
	{
	    /* Put back the line */
	    if (this.in != null)
	    {
		String putback = new String(statusLine + "\n");
		this.in = new SequenceInputStream(new StringBufferInputStream(putback), in);
	    }
	    /* Fake a status line and upgrade to HTTP/1.0 */
	    statusLine = "HTTP/1.0 200 OK";
	    return;
	}
	
	readHeaders(in);
	int code = getStatusCode();

	/* RFC 2068: 204 and 304 MUST NOT contain a message body. */
	switch (code)
	{
	case 204: /* No Content */
	case 304: /* Not Modified */
	    /* Ignore the message body if it exists */
	    if (containsHeaderField("Content-length"))
	    {		
		int contentLength = 0;
		try 
		{
		    contentLength = Integer.parseInt(getHeaderField("Content-length"));
		}
		catch (NumberFormatException e)
		{
		}
		int n;
		byte buffer[] = new byte[8192];
		while ((n = in.read(buffer, 0, buffer.length)) > 0)
		{
		    /* ignore */
		}
		removeHeaderField("Content-length");
	    }
	    break;
	}
    }

    public boolean hasContent()
    {
	switch (getStatusCode())
	{
	case 204:
	case 304:
	    return false;

	default:
	    return true;
	}
    }

    public String getProtocol()
    {
	StringTokenizer st = new StringTokenizer(statusLine);
	String protocol = (String) st.nextToken();
	return protocol;
    }

    public int getStatusCode()
    {
	if (statusCode == -1)
	{
	    StringTokenizer st = new StringTokenizer(statusLine);
	    String protocol = (String) st.nextToken();
	    String status = (String) st.nextToken();

	    try
	    {
		statusCode = Integer.parseInt(status);
	    }
	    catch (NumberFormatException e)
	    {
		System.out.println("Malformed or missing status code");
		statusCode = 0;
	    }
	}
	
	return statusCode;
    }

    private Hashtable headerParser(String header)
    {
	Hashtable table = new Hashtable();
	String type = getHeaderField(header);
	if (type == null)
	{
	    return table;
	}

	StringTokenizer st = new StringTokenizer(type, ";");
	int count = 0;
	while (st.hasMoreTokens())
	{
	    String token = st.nextToken();
	    token = token.trim();
	    String name;
	    String value;
	    int i = token.indexOf('=');
	    if (i != -1)
	    {
		name = token.substring(0, i);
		value = token.substring(i+1);
	    }
	    else
	    {
		name = token;
		value = "";
	    }

	    if (count == 0)
	    {
		table.put(header, name);
	    }
	    else
	    {
		table.put(name, value);
	    }

	    count++;
	}

	return table;
    }

    public String getContentType()
    {
	Hashtable table = headerParser("Content-type");
	return(String) table.get("Content-type");
    }

    public String getBoundary()
    {
	Hashtable table = headerParser("Content-type");
	return(String) table.get("boundary");
    }

    public String getTransferEncoding()
    {
	Hashtable table = headerParser("Transfer-Encoding");
	return(String) table.get("Transfer-Encoding");
    }

    public int getChunkSize(InputStream in) throws IOException
    {
	String line = readLine(in);
	line = line.trim(); /* apache can have trailing spaces */
	int size = -1;
	try
	{
	    size = Integer.valueOf(line, 16).intValue();
	}
	catch (NumberFormatException e)
	{
	    System.out.println(e);
	}
	return size;
    }

    public void getChunkedFooter(InputStream in) throws IOException
    {
	for (;;)
	{
	    String line = readLine(in);
	    if (line == null)
	    {
		break;
	    }
	    int i = line.indexOf(':');
	    if (i == -1)
	    {
		break;
	    }
	}
    }

    public void setStatusLine(String line)
    {
	this.statusLine = line;
    }

    public static Reply createRedirect(String url)
    {
	Reply r = new Reply();
	r.setStatusLine("HTTP/1.0 302 Moved Temporarily");
	r.setHeaderField("Location", url);
	return r;
    }
}
