/*
 * @(#)HTTPResponse.cpp
 *
 * This file is part of webCDwriter - Network CD Writing.
 *
 * Copyright (C) 2002 Jörg P. M. Haeger
 *
 * webCDwriter is free software. See CDWserver.cpp for details.
 *
 * Jörg Haeger, 30.04.2002
 */

#include "File.h"
#include "HTTPResponse.h"
#include "Log.h"
#include "PrintWriter.h"
#include "Version.h"

const char CRLF[] = "\r\n";

HTTPResponse::HTTPResponse() {
	setStatusCode(200);
	contentType = "application/octet-stream";
	entityBytesTransferred = 0;
}

HTTPResponse::HTTPResponse(HTTPResponse *response) {
	*this = *response;
	delete response;
}

HTTPResponse::~HTTPResponse() {
}

String *operator+(const char *str1, String &str2) {
	String *str = new String(str1);
	*str + str2;
	return str;
}

String *HTTPResponse::getErrorHTML() {
	String str = "";
	str = str + "<html>\n"
		+ "<head><title>" + reasonPhrase + "</title></head>\n"
		+ "<body><h1>Error " + statusCode + ": "
		+ reasonPhrase + "</h1></body>\n"
		+ "</html>\n";
	return new String(str);
}

HTTPResponse *HTTPResponse::movedPermanently(String &location) {
	HTTPResponse *response = new HTTPResponse();
	response->setStatusCode(301);
	response->setLocation(location);
	String entity = response->getErrorHTML();
	String type = "text/html";
	response->setEntity(entity, type);
	return response;
}

HTTPResponse *HTTPResponse::notFound() {
	HTTPResponse *response = new HTTPResponse();
	response->setStatusCode(404);
	String entity = response->getErrorHTML();
	String type = "text/html";
	response->setEntity(entity, type);
	return response;
}

HTTPResponse *HTTPResponse::notImplemented() {
	HTTPResponse *response = new HTTPResponse();
	response->setStatusCode(501);
	String entity = response->getErrorHTML();
	String type = "text/html";
	response->setEntity(entity, type);
	return response;
}

void HTTPResponse::setEntity(File &file) {
	entityStream = new FileInputStream(file);

	contentLength = "Content-Length: ";
	contentLength = contentLength + file.getSize() + CRLF;

	String type = "";
	if (file.getPath().endsWith(".html"))
		type = "text/html";
	else if (file.getPath().endsWith(".ico"))
		type = "image/x-icon";
	else if (file.getPath().endsWith(".jar"))
		type = "application/x-jar";
	else if (file.getPath().endsWith(".jnlp"))
		type = "application/x-java-jnlp-file";
	else if (file.getPath().endsWith(".png"))
		type = "image/png";
	else if (file.getPath().endsWith(".gif"))
		type = "image/gif";
	else if (file.getPath().endsWith(".java"))
		type = "text/plain";
	else if (file.getPath().endsWith(".txt"))
		type = "text/plain";
	else
		type = "application/octet-stream";

	contentType = "Content-Type: ";
	contentType = contentType + type + CRLF;
}

void HTTPResponse::setEntity(String &body, String &type) {
	contentLength = "Content-Length: ";
	contentLength = contentLength + body.length() + CRLF;
	contentType = "Content-Type: ";
	contentType = contentType + type + CRLF;
	entityBody = body;
}

void HTTPResponse::setLocation(String &aLocation) {
	location = "Location: ";
	location = location + aLocation + CRLF;
}

void HTTPResponse::setStatusCode(int code) {
	statusCode = code;
	switch (code) {
		case 200:
			reasonPhrase = "OK";
		break;
		case 301:
			reasonPhrase = "Moved Permanently";
		break;
		case 404:
			reasonPhrase = "Not Found";
		break;
		case 501:
			reasonPhrase = "Not Implemented";
		break;
	}
}

void HTTPResponse::write(class PrintWriter &writer) {
	writeHead(writer);
	writer.write(entityBody);

	entityBytesTransferred = entityBody.length();
	while (1) {
		char buf[4096];
		int n = entityStream.read(buf, 0, sizeof buf);
		if (n <= 0)
			break;
		writer.write(buf, 0, n);
		entityBytesTransferred += n;
	}

	writer.flush();
}

void HTTPResponse::writeHead(class PrintWriter &writer) {
	String s = "";
	s = s + "HTTP/1.0 " + statusCode + " " + reasonPhrase + CRLF
	// Response-Header
		+ location
		+ "Server: " + Version.product + "/" + Version.version + CRLF
		+ "Connection: close" + CRLF
	// Entity Header Fields
		+ contentLength
		+ contentType
		+ CRLF;

	writer.write(s);
	writer.flush();
}
