#include "server.h"
#include "Session.h"
#include "Response.h"
#include <time.h>

static void
response(HTLIB* o, const char* uri, const Response* res, const char* method)
{
	HTLIB_ERROR err;

	/* status line */
	if (HTLIB_SendResponse(o, -1,
						   res->status, res->status_msg,
						   res->headers,
						   res->header_len,
						   res->body,
						   res->body ? strlen(res->body) : 0,
						   &err)==FALSE) {
		fprintf(stderr, "SendResponse failed err=%d:%s\n",
				err, HTLIB_GetErrorMessage(err));
		fprintf(stdout, "[%d ---]: %.16s\n", res->status, uri);
		return;
	}

	char buf30[30];
	HTLIB_SetDate(buf30, NULL);
	fprintf(stdout, "[%s] %d %d: \"%s %.16s\"\n", buf30, res->status,
			res->body ? strlen(res->body) : 0, uri? method: NULL, uri);
}

static void
responseError(HTLIB* o, const char* uri, int status, const char* method)
{
	const Response* res = findErrorResponse(status);
	if (res == NULL) {
		fprintf(stderr, "not found %d\n", status);
		return;
	}
	response(o, uri, res, method);
}

static void
responseForUri(HTLIB* o, const char* uri, const char* method)
{
	const Response* res = findResponse(uri);
	if (res == NULL) {
		responseError(o, uri, 404, method);
		return;
	}
	response(o, uri, res, method);
}

void*
doSession(void* arg)
{
	HTLIB ht;
	HTLIB_ERROR err;
	char send_buffer[1000];
	char rec_buffer[1000];
	if (HTLIB_Init(&ht,
				   send_buffer, sizeof(send_buffer),
				   rec_buffer, sizeof(rec_buffer), &err)==FALSE) {
		fprintf(stderr, "HTLIB_Init failed err=%d:%s\n",
				err, HTLIB_GetErrorMessage(err));
		return NULL;
	}
	ht.agent_or_server_name = "HtLib Server/0.9";
	
	HTLIB_Attach(&ht, (int)arg);
	
	while(TRUE) {
		const char* uri;
		const char* method;
		HTLIB_Header header_buffer[30];
		HTLIB_USHORT blen = 30;
		
		if ((uri=HTLIB_ReceiveRequest(&ht,
									  10000,
									  &method,
									  header_buffer, &blen,
									  NULL,
									  &err))==NULL) {
			fprintf(stderr, "ReceiveRequest failed err=%d:%s\n",
					err, HTLIB_GetErrorMessage(err));
			if (err == HTLIB_E_TIMEOUT) {
				fprintf(stderr, "restart\n");
				continue;
			}
			if (err != HTLIB_E_DISCONNECTED) {
				responseError(&ht, "<undetermined>", 400, method);
			}
			break;
		}

		if (strcmp(uri, "/exit")==0) {
			HTLIB_CancelAll(TRUE);
			sleep(1);
			exit(0);
		}
		if (strcmp(method, "POST")==0 || strcmp(method, "PUT")==0) {
			int index;
			if ((index=HTLIB_Find(header_buffer, blen, "Expect"))!=-1) {
				if (header_buffer[index].value != NULL &&
					strcasecmp(header_buffer[index].value,
							   "100-continue")==0) {
					if (HTLIB_SendResponse(&ht, -1,
										   100, "Continue",
										   NULL, 0,
										   NULL, 0,
										   &err)==FALSE) {
						fprintf(stderr, "Send 100 failed err=%d:%s\n",
								err, HTLIB_GetErrorMessage(err));
						break;
					}
				}
			}
		}
		int len;
		char data[1000];
		while ((len=HTLIB_ReceiveBody(&ht, -1,
									  data, sizeof(data), &err))>0) {
			/* ignore body */
		}
		responseForUri(&ht, uri, method);
	}
	HTLIB_Uninit(&ht);
	fprintf(stderr, "session ended\n");
	return NULL;
}
