#include "htlib2.h"
#include "HtLib_.h"
#include "Socket.h"
#include "Header.h"
#include "Thread.h"
#include "Sender.h"

HTLIB_BOOL
M(HTLIB,Init)(HTLIB* o,
			  char* send_buffer, HTLIB_USHORT send_len,
			  char* rec_buffer, HTLIB_USHORT rec_len,
			  HTLIB_ERROR* err)
{
	memset(o, 0, sizeof(HTLIB));

	o->soc = -1;
	o->_rec_buffer = rec_buffer;
	o->_rec_buffer_len = rec_len;
	o->_send_buffer = send_buffer;
	o->_send_buffer_len = send_len;

	/* now, no errorable initializing */
	return TRUE;
}

void
M(HTLIB,Uninit)(HTLIB* o)
{
	M(HTLIB,Close)(o);
}

BOOL
M(HTLIB,Open)(HTLIB_HANDLE o,
		   const struct sockaddr* addr,
		   socklen_t addr_len,
		   HTLIB_ERROR* err)
{
	if (M(Sender,Open)(o, addr, addr_len, err)==FALSE) {
		return FALSE;
	}
	return TRUE;
}

void
M(HTLIB,Attach)(HTLIB_HANDLE o, int socket)
{
	M(HTLIB,Close)(o);
	o->soc = socket;
	M(HTLIB,Reset)(o);
}

void
M(HTLIB,Reset)(HTLIB_HANDLE o)
{
	o->_send_content_length = 0;
	o->_send_content_transfered = 0;
	o->_read_index = 0;
	o->_rec_content_length = 0;
	o->_rec_content_transfered = 0;
	o->_header = NULL;
	o->_body_index = 0;

	o->_flags = 0;
	FLAG_SET(FLAG_KEEP_ALIVE, o->_flags);
}

void
M(HTLIB,Close)(HTLIB_HANDLE o)
{
	M(Sender,Close)(o);
}

/* flag for all handles */
static volatile BOOL s_is_canceled = FALSE;
static pthread_mutex_t s_lock = PTHREAD_MUTEX_INITIALIZER;

BOOL
M(HTLIB,CheckCanceled)(HTLIB* o, HTLIB_ERROR* err)
{
	int canceled = 0;
	M(Mutex,Lock)(&s_lock);
	if (o->_is_canceled) {
		canceled |= 1;
	}
	if (s_is_canceled) {
		canceled |= 2;
	}
	M(Mutex,Unlock)(&s_lock);

	if (canceled != 0) {
		*err = HTLIB_E_CANCELED;
		LOGWARN("canceled %d\n", canceled);
		return FALSE;
	}
	return TRUE;
}

void
M(HTLIB,Cancel)(HTLIB* o, BOOL trueIfCancel)
{
	LOGERR("HTLIB_Cancel: %d\n", trueIfCancel);
	M(Mutex,Lock)(&s_lock);
	o->_is_canceled = trueIfCancel;
	M(Mutex,Unlock)(&s_lock);
}
void
M(HTLIB,CancelAll)(BOOL trueIfCancel)
{
	LOGERR("HTLIB_Cancel: %d\n", trueIfCancel);
	M(Mutex,Lock)(&s_lock);
	s_is_canceled = trueIfCancel;
	M(Mutex,Unlock)(&s_lock);
}

const char*
G(GetErrorMessage)(HTLIB_ERROR err)
{
	const struct ErrMsg {
		int err;
		const char* msg;
	} c_msg[] = {
#define ERRMSG(e) { e, #e }
		ERRMSG(HTLIB_E_NO_ERROR),

		ERRMSG(HTLIB_E_INVALID_ARG),
		ERRMSG(HTLIB_E_INVALID_STATE),
		ERRMSG(HTLIB_E_OUT_OF_MEMORY),
		ERRMSG(HTLIB_E_TIMEOUT),
		ERRMSG(HTLIB_E_INVALID_SYNTAX),
		ERRMSG(HTLIB_E_CANCELED),

		ERRMSG(HTLIB_E_DISCONNECTED),
		
		ERRMSG(HTLIB_E_FATAL),
		ERRMSG(HTLIB_E_NOT_IMPLEMENTED),
	
		ERRMSG(HTLIB_E_SYSTEM),
	};
	int i;
	for (i=0; i<sizeof(c_msg)/sizeof(c_msg[0]); i++) {
		if (c_msg[i].err == err) {
			return c_msg[i].msg;
		}
	}
	return "(undefined)";
}



