package httpRecorder.proxy;

/*
 * Disclaimer:
 * The following source code is sample code created by IBM Corporation.  
 * This sample code is not part of any standard IBM product and is provided 
 * to you solely for the purpose of assisting you in the development of your 
 * applications.  The code is provided 'AS IS', without warranty or condition 
 * of any kind.  IBM shall not be liable for any damages arising out of your 
 * use of the sample code, even if IBM has been advised of the possibility of 
 * such damages.
 */

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

/**
 * The response is the object that stores the data that is
 * sent from the server to the client (usually a browser).
 */ 
public class HttpResponse
extends HttpElement
{
	private static final int BUFFER = 2048;
	
	private int code;
	private String detail;
	private HttpRequest request;
	
	public HttpResponse(HttpRequest request)
	{
		if(request.getResponse() != null)
			throw new IllegalArgumentException("The request has already a response");
			
		this.request = request;
		request.setResponse(this);
	}
	
	public HttpRequest getRequest()
	{
		return request;
	}
	
	protected void setBody(InputStream inputStream)
	throws IOException
	{
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		
		String transferEncoding = getHeaderValue(IHttpHeaderName.TRANSFER_ENCODING);
		int contentLength = getHeaderIntValue(IHttpHeaderName.CONTENT_LENGTH);
		boolean keepAlive = IHttpHeaderValue.KEEP_ALIVE.equals(getHeaderValue(IHttpHeaderName.CONNECTION));
		
		if((!keepAlive) && (contentLength <= 0) && (transferEncoding == null))
		{
			byte[] buffer = new byte[BUFFER];
			int length = 0;
			while((length=inputStream.read(buffer)) != -1)
				outputStream.write(buffer, 0, length);			
		}
		else
		{
			if(((getCode() >= 100) && (getCode() < 200)) || (getCode() == 204) || (getCode() == 304)) 
				return;
	
			if(
				(transferEncoding != null) &&
				(IHttpHeaderValue.CHUNCKED.equals(transferEncoding)
				||IHttpHeaderValue.GZIP.equals(transferEncoding)
				||IHttpHeaderValue.COMPRESSED.equals(transferEncoding)
				||IHttpHeaderValue.DEFLATE.equals(transferEncoding)))
			{
				//This code doesn't handle encoding.
			}
			else
			{
				if(contentLength > 0)
				{
					byte[] buffer = new byte[contentLength];					
					int available = inputStream.available();
					
					if(available >= contentLength)
					{
						inputStream.read(buffer);
					}
					else if(available > 0)
					{
						int size = 1;
						int length = 0;
						long start = System.currentTimeMillis();
						while((length != -1) && (size <= contentLength))
						{
							length = inputStream.read(buffer, size-1, inputStream.available());
							size+=length;
							
							if(System.currentTimeMillis() - start > 5000)
								break;
						}
					}

					outputStream.write(buffer);
				}
			}
		}
		
		setBody(outputStream.toByteArray());
	}

	protected void parse()
	throws IOException
	{
		String line = super.getLine();
		String token = " ";
		int index = line.indexOf(token);
		if(index < 0)
			return;
			
		setVersion(line.substring(0, index));
		
		int pos = index+token.length();
		index = line.indexOf(token, pos);
		if(index < 0)
			return;
		
		try
		{
			code = Integer.parseInt(line.substring(pos, index));
		}
		catch(NumberFormatException e)
		{
		}
			
		pos = index+token.length();
		if(pos < line.length())
			detail = line.substring(pos);
	}
	
	public String getDetail()
	{
		return detail;
	}

	public int getCode()
	{
		return code;
	}

	protected StringBuffer xmlAttributes()
	{
		StringBuffer attributes = new StringBuffer();
		attributes.append(ProxyUtil.xmlAttribute("code", Integer.toString(getCode())));
		attributes.append(ProxyUtil.xmlAttribute("detail", getDetail()));
		if(getRequest() != null)
			attributes.append(ProxyUtil.xmlAttribute("requestCreationTime", Long.toString(getRequest().getCreationTime())));

		attributes.append(super.xmlAttributes());
		
		return attributes;
	}

	protected String xmlTopElement()
	{
		return "response";
	}
}
