/**
 * @file msg.c Message functions
 *
 * purple
 *
 * Purple is the legal property of its developers, whose names are too numerous
 * to list here.  Please refer to the COPYRIGHT file distributed with this
 * source distribution.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "nateon.h"
#include "msg.h"

NateonMessage *
nateon_message_new(NateonMsgType type)
{
	NateonMessage *msg;

	msg = g_new0(NateonMessage, 1);
	msg->type = type;

#ifdef NATEON_DEBUG_MSG
	purple_debug_info("nateon", "message new (%p)(%d)\n", msg, type);
#endif

//	msg->attr_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);

	nateon_message_ref(msg);

	return msg;
}

void
nateon_message_destroy(NateonMessage *msg)
{
	g_return_if_fail(msg != NULL);

	if (msg->ref_count > 0)
	{
		nateon_message_unref(msg);

		return;
	}

#ifdef NATEON_DEBUG_MSG
	purple_debug_info("nateon", "message destroy (%p)\n", msg);
#endif

//	if (msg->remote_user != NULL)
//		g_free(msg->remote_user);

	if (msg->body != NULL)
		g_free(msg->body);

//	if (msg->content_type != NULL)
//		g_free(msg->content_type);
//
//	if (msg->charset != NULL)
//		g_free(msg->charset);
//
//	g_hash_table_destroy(msg->attr_table);
//	g_list_free(msg->attr_list);

	g_free(msg);
}

NateonMessage *
nateon_message_ref(NateonMessage *msg)
{
	g_return_val_if_fail(msg != NULL, NULL);

	msg->ref_count++;

#ifdef NATEON_DEBUG_MSG
	purple_debug_info("nateon", "message ref (%p)[%d]\n", msg, msg->ref_count);
#endif

	return msg;
}

NateonMessage *
nateon_message_unref(NateonMessage *msg)
{
	g_return_val_if_fail(msg != NULL, NULL);
	g_return_val_if_fail(msg->ref_count > 0, NULL);

	msg->ref_count--;

#ifdef NATEON_DEBUG_MSG
	purple_debug_info("nateon", "message unref (%p)[%d]\n", msg, msg->ref_count);
#endif

	if (msg->ref_count == 0)
	{
		nateon_message_destroy(msg);

		return NULL;
	}

	return msg;
}

NateonMessage *
nateon_message_new_plain(const char *message)
{
	NateonMessage *msg;
//	char *message_cr;
	char *message_enc;

	msg = nateon_message_new(NATEON_MSG_TEXT);
//	nateon_message_set_attr(msg, "User-Agent", "Purple/" VERSION);
//	nateon_message_set_content_type(msg, "text/plain");
//	nateon_message_set_charset(msg, "UTF-8");
//	nateon_message_set_flag(msg, 'A');
//	nateon_message_set_attr(msg, "X-MMS-IM-Format",
//						 "FN=MS%20Sans%20Serif; EF=; CO=0; PF=0");
//
//	message_cr = purple_str_add_cr(message);
//	nateon_message_set_bin_data(msg, message_cr, strlen(message_cr));
//	g_free(message_cr);

	message_enc = g_strdup_printf("MSG %s", message);
	nateon_message_set_bin_data(msg, message_enc, strlen(message_enc));
	g_free(message_enc);

	return msg;
}

//NateonMessage *
//nateon_message_new_nateonslp(void)
//{
//	NateonMessage *msg;
//
//	msg = nateon_message_new(NATEON_MSG_SLP);
//
//	nateon_message_set_attr(msg, "User-Agent", NULL);
//
//	msg->nateonslp_message = TRUE;
//
//	nateon_message_set_flag(msg, 'D');
//	nateon_message_set_content_type(msg, "application/x-nateonmsgrp2p");
//
//	return msg;
//}
//
//NateonMessage *
//nateon_message_new_nudge(void)
//{
//	NateonMessage *msg;
//
//	msg = nateon_message_new(NATEON_MSG_NUDGE);
//	nateon_message_set_content_type(msg, "text/x-nateonmsgr-datacast\r\n");
//	nateon_message_set_flag(msg, 'N');
//	nateon_message_set_attr(msg,"ID","1\r\n");
//
//	return msg;
//}
//
//void
//nateon_message_parse_slp_body(NateonMessage *msg, const char *body, size_t len)
//{
//	NateonSlpHeader header;
//	const char *tmp;
//	int body_len;
//
//	tmp = body;
//
//	if (len < sizeof(header)) {
//		g_return_if_reached();
//	}
//
//	/* Import the header. */
//	memcpy(&header, tmp, sizeof(header));
//	tmp += sizeof(header);
//
//	msg->nateonslp_header.session_id = GUINT32_FROM_LE(header.session_id);
//	msg->nateonslp_header.id         = GUINT32_FROM_LE(header.id);
//	msg->nateonslp_header.offset     = GUINT64_FROM_LE(header.offset);
//	msg->nateonslp_header.total_size = GUINT64_FROM_LE(header.total_size);
//	msg->nateonslp_header.length     = GUINT32_FROM_LE(header.length);
//	msg->nateonslp_header.flags      = GUINT32_FROM_LE(header.flags);
//	msg->nateonslp_header.ack_id     = GUINT32_FROM_LE(header.ack_id);
//	msg->nateonslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id);
//	msg->nateonslp_header.ack_size   = GUINT64_FROM_LE(header.ack_size);
//
//	/* Import the body. */
//	body_len = len - (tmp - body);
//	/* msg->body_len = msg->nateonslp_header.length; */
//
//	if (body_len > 0) {
//		msg->body_len = len - (tmp - body);
//		msg->body = g_malloc0(msg->body_len + 1);
//		memcpy(msg->body, tmp, msg->body_len);
//		tmp += body_len;
//	}
//}
//
//void
//nateon_message_parse_payload(NateonMessage *msg,
//						  const char *payload, size_t payload_len)
//{
//	char *tmp_base, *tmp;
//	const char *content_type;
//	char *end;
//	char **elems, **cur, **tokens;
//
//	g_return_if_fail(payload != NULL);
//
//	tmp_base = tmp = g_malloc0(payload_len + 1);
//	memcpy(tmp_base, payload, payload_len);
//
//	/* Parse the attributes. */
//	end = strstr(tmp, "\r\n\r\n");
//	/* TODO? some clients use \r delimiters instead of \r\n, the official client
//	 * doesn't send such messages, but does handle receiving them. We'll just
//	 * avoid crashing for now */
//	if (end == NULL) {
//		g_free(tmp_base);
//		g_return_if_reached();
//	}
//	*end = '\0';
//
//	elems = g_strsplit(tmp, "\r\n", 0);
//
//	for (cur = elems; *cur != NULL; cur++)
//	{
//		const char *key, *value;
//
//		tokens = g_strsplit(*cur, ": ", 2);
//
//		key = tokens[0];
//		value = tokens[1];
//
//		if (!strcmp(key, "MIME-Version"))
//		{
//			g_strfreev(tokens);
//			continue;
//		}
//
//		if (!strcmp(key, "Content-Type"))
//		{
//			char *charset, *c;
//
//			if ((c = strchr(value, ';')) != NULL)
//			{
//				if ((charset = strchr(c, '=')) != NULL)
//				{
//					charset++;
//					nateon_message_set_charset(msg, charset);
//				}
//
//				*c = '\0';
//			}
//
//			nateon_message_set_content_type(msg, value);
//		}
//		else
//		{
//			nateon_message_set_attr(msg, key, value);
//		}
//
//		g_strfreev(tokens);
//	}
//
//	g_strfreev(elems);
//
//	/* Proceed to the end of the "\r\n\r\n" */
//	tmp = end + 4;
//
//	/* Now we *should* be at the body. */
//	content_type = nateon_message_get_content_type(msg);
//
//	if (content_type != NULL &&
//		!strcmp(content_type, "application/x-nateonmsgrp2p"))
//	{
//		NateonSlpHeader header;
//		NateonSlpFooter footer;
//		int body_len;
//
//		if (payload_len - (tmp - tmp_base) < sizeof(header)) {
//			g_free(tmp_base);
//			g_return_if_reached();
//		}
//
//		msg->nateonslp_message = TRUE;
//
//		/* Import the header. */
//		memcpy(&header, tmp, sizeof(header));
//		tmp += sizeof(header);
//
//		msg->nateonslp_header.session_id = GUINT32_FROM_LE(header.session_id);
//		msg->nateonslp_header.id         = GUINT32_FROM_LE(header.id);
//		msg->nateonslp_header.offset     = GUINT64_FROM_LE(header.offset);
//		msg->nateonslp_header.total_size = GUINT64_FROM_LE(header.total_size);
//		msg->nateonslp_header.length     = GUINT32_FROM_LE(header.length);
//		msg->nateonslp_header.flags      = GUINT32_FROM_LE(header.flags);
//		msg->nateonslp_header.ack_id     = GUINT32_FROM_LE(header.ack_id);
//		msg->nateonslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id);
//		msg->nateonslp_header.ack_size   = GUINT64_FROM_LE(header.ack_size);
//
//		body_len = payload_len - (tmp - tmp_base) - sizeof(footer);
//
//		/* Import the body. */
//		if (body_len > 0) {
//			msg->body_len = body_len;
//			msg->body = g_malloc0(msg->body_len + 1);
//			memcpy(msg->body, tmp, msg->body_len);
//			tmp += body_len;
//		}
//
//		/* Import the footer. */
//		if (body_len >= 0) {
//			memcpy(&footer, tmp, sizeof(footer));
//			tmp += sizeof(footer);
//			msg->nateonslp_footer.value = GUINT32_FROM_BE(footer.value);
//		}
//	}
//	else
//	{
//		if (payload_len - (tmp - tmp_base) > 0) {
//			msg->body_len = payload_len - (tmp - tmp_base);
//			msg->body = g_malloc0(msg->body_len + 1);
//			memcpy(msg->body, tmp, msg->body_len);
//		}
//	}
//
//	g_free(tmp_base);
//}
//
//NateonMessage *
//nateon_message_new_from_cmd(NateonSession *session, NateonCommand *cmd)
//{
//	NateonMessage *msg;
//
//	g_return_val_if_fail(cmd != NULL, NULL);
//
//	msg = nateon_message_new(NATEON_MSG_UNKNOWN);
//
//	msg->remote_user = g_strdup(cmd->params[0]);
//	/* msg->size = atoi(cmd->params[2]); */
//	msg->cmd = cmd;
//
//	return msg;
//}
//
//char *
//nateon_message_gen_slp_body(NateonMessage *msg, size_t *ret_size)
//{
//	NateonSlpHeader header;
//
//	char *tmp, *base;
//	const void *body;
//	size_t len, body_len;
//
//	g_return_val_if_fail(msg != NULL, NULL);
//
//	len = NATEON_BUF_LEN;
//
//	base = tmp = g_malloc(len + 1);
//
//	body = nateon_message_get_bin_data(msg, &body_len);
//
//	header.session_id = GUINT32_TO_LE(msg->nateonslp_header.session_id);
//	header.id         = GUINT32_TO_LE(msg->nateonslp_header.id);
//	header.offset     = GUINT64_TO_LE(msg->nateonslp_header.offset);
//	header.total_size = GUINT64_TO_LE(msg->nateonslp_header.total_size);
//	header.length     = GUINT32_TO_LE(msg->nateonslp_header.length);
//	header.flags      = GUINT32_TO_LE(msg->nateonslp_header.flags);
//	header.ack_id     = GUINT32_TO_LE(msg->nateonslp_header.ack_id);
//	header.ack_sub_id = GUINT32_TO_LE(msg->nateonslp_header.ack_sub_id);
//	header.ack_size   = GUINT64_TO_LE(msg->nateonslp_header.ack_size);
//
//	memcpy(tmp, &header, 48);
//	tmp += 48;
//
//	if (body != NULL)
//	{
//		memcpy(tmp, body, body_len);
//		tmp += body_len;
//	}
//
//	if (ret_size != NULL)
//		*ret_size = tmp - base;
//
//	return base;
//}
//
//char *
//nateon_message_gen_payload(NateonMessage *msg, size_t *ret_size)
//{
//	GList *l;
//	char *n, *base, *end;
//	int len;
//	size_t body_len;
//	const void *body;
//
//	g_return_val_if_fail(msg != NULL, NULL);
//
//	len = NATEON_BUF_LEN;
//
//	base = n = end = g_malloc(len + 1);
//	end += len;
//
//	/* Standard header. */
//	if (msg->charset == NULL)
//	{
//		g_snprintf(n, len,
//				   "MIME-Version: 1.0\r\n"
//				   "Content-Type: %s\r\n",
//				   msg->content_type);
//	}
//	else
//	{
//		g_snprintf(n, len,
//				   "MIME-Version: 1.0\r\n"
//				   "Content-Type: %s; charset=%s\r\n",
//				   msg->content_type, msg->charset);
//	}
//
//	n += strlen(n);
//
//	for (l = msg->attr_list; l != NULL; l = l->next)
//	{
//		const char *key;
//		const char *value;
//
//		key = l->data;
//		value = nateon_message_get_attr(msg, key);
//
//		g_snprintf(n, end - n, "%s: %s\r\n", key, value);
//		n += strlen(n);
//	}
//
//	n += g_strlcpy(n, "\r\n", end - n);
//
//	body = nateon_message_get_bin_data(msg, &body_len);
//
//	if (msg->nateonslp_message)
//	{
//		NateonSlpHeader header;
//		NateonSlpFooter footer;
//
//		header.session_id = GUINT32_TO_LE(msg->nateonslp_header.session_id);
//		header.id         = GUINT32_TO_LE(msg->nateonslp_header.id);
//		header.offset     = GUINT64_TO_LE(msg->nateonslp_header.offset);
//		header.total_size = GUINT64_TO_LE(msg->nateonslp_header.total_size);
//		header.length     = GUINT32_TO_LE(msg->nateonslp_header.length);
//		header.flags      = GUINT32_TO_LE(msg->nateonslp_header.flags);
//		header.ack_id     = GUINT32_TO_LE(msg->nateonslp_header.ack_id);
//		header.ack_sub_id = GUINT32_TO_LE(msg->nateonslp_header.ack_sub_id);
//		header.ack_size   = GUINT64_TO_LE(msg->nateonslp_header.ack_size);
//
//		memcpy(n, &header, 48);
//		n += 48;
//
//		if (body != NULL)
//		{
//			memcpy(n, body, body_len);
//
//			n += body_len;
//		}
//
//		footer.value = GUINT32_TO_BE(msg->nateonslp_footer.value);
//
//		memcpy(n, &footer, 4);
//		n += 4;
//	}
//	else
//	{
//		if (body != NULL)
//		{
//			memcpy(n, body, body_len);
//			n += body_len;
//		}
//	}
//
//	if (ret_size != NULL)
//	{
//		*ret_size = n - base;
//
//		if (*ret_size > 1664)
//			*ret_size = 1664;
//	}
//
//	return base;
//}
//
//void
//nateon_message_set_flag(NateonMessage *msg, char flag)
//{
//	g_return_if_fail(msg != NULL);
//	g_return_if_fail(flag != 0);
//
//	msg->flag = flag;
//}
//
//char
//nateon_message_get_flag(const NateonMessage *msg)
//{
//	g_return_val_if_fail(msg != NULL, 0);
//
//	return msg->flag;
//}

void
nateon_message_set_bin_data(NateonMessage *msg, const void *data, size_t len)
{
	g_return_if_fail(msg != NULL);

	/* There is no need to waste memory on data we cannot send anyway */
//	if (len > 1664)
//		len = 1664;

	if (msg->body != NULL)
		g_free(msg->body);

	if (data != NULL && len > 0)
	{
		msg->body = g_malloc0(len + 1);
		memcpy(msg->body, data, len);
		msg->body_len = len;
	}
	else
	{
		msg->body = NULL;
		msg->body_len = 0;
	}
}

//const void *
//nateon_message_get_bin_data(const NateonMessage *msg, size_t *len)
//{
//	g_return_val_if_fail(msg != NULL, NULL);
//
//	if (len)
//		*len = msg->body_len;
//
//	return msg->body;
//}
//
//void
//nateon_message_set_content_type(NateonMessage *msg, const char *type)
//{
//	g_return_if_fail(msg != NULL);
//
//	if (msg->content_type != NULL)
//		g_free(msg->content_type);
//
//	msg->content_type = (type != NULL) ? g_strdup(type) : NULL;
//}
//
//const char *
//nateon_message_get_content_type(const NateonMessage *msg)
//{
//	g_return_val_if_fail(msg != NULL, NULL);
//
//	return msg->content_type;
//}
//
//void
//nateon_message_set_charset(NateonMessage *msg, const char *charset)
//{
//	g_return_if_fail(msg != NULL);
//
//	if (msg->charset != NULL)
//		g_free(msg->charset);
//
//	msg->charset = (charset != NULL) ? g_strdup(charset) : NULL;
//}
//
//const char *
//nateon_message_get_charset(const NateonMessage *msg)
//{
//	g_return_val_if_fail(msg != NULL, NULL);
//
//	return msg->charset;
//}
//
//void
//nateon_message_set_attr(NateonMessage *msg, const char *attr, const char *value)
//{
//	const char *temp;
//	char *new_attr;
//
//	g_return_if_fail(msg != NULL);
//	g_return_if_fail(attr != NULL);
//
//	temp = nateon_message_get_attr(msg, attr);
//
//	if (value == NULL)
//	{
//		if (temp != NULL)
//		{
//			GList *l;
//
//			for (l = msg->attr_list; l != NULL; l = l->next)
//			{
//				if (!g_ascii_strcasecmp(l->data, attr))
//				{
//					msg->attr_list = g_list_remove(msg->attr_list, l->data);
//
//					break;
//				}
//			}
//
//			g_hash_table_remove(msg->attr_table, attr);
//		}
//
//		return;
//	}
//
//	new_attr = g_strdup(attr);
//
//	g_hash_table_insert(msg->attr_table, new_attr, g_strdup(value));
//
//	if (temp == NULL)
//		msg->attr_list = g_list_append(msg->attr_list, new_attr);
//}
//
//const char *
//nateon_message_get_attr(const NateonMessage *msg, const char *attr)
//{
//	g_return_val_if_fail(msg != NULL, NULL);
//	g_return_val_if_fail(attr != NULL, NULL);
//
//	return g_hash_table_lookup(msg->attr_table, attr);
//}
//
//GHashTable *
//nateon_message_get_hashtable_from_body(const NateonMessage *msg)
//{
//	GHashTable *table;
//	size_t body_len;
//	const char *body;
//	char **elems, **cur, **tokens, *body_str;
//
//	g_return_val_if_fail(msg != NULL, NULL);
//
//	table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
//
//	body = nateon_message_get_bin_data(msg, &body_len);
//
//	g_return_val_if_fail(body != NULL, NULL);
//
//	body_str = g_strndup(body, body_len);
//	elems = g_strsplit(body_str, "\r\n", 0);
//	g_free(body_str);
//
//	for (cur = elems; *cur != NULL; cur++)
//	{
//		if (**cur == '\0')
//			break;
//
//		tokens = g_strsplit(*cur, ": ", 2);
//
//		if (tokens[0] != NULL && tokens[1] != NULL)
//			g_hash_table_insert(table, tokens[0], tokens[1]);
//
//		g_free(tokens);
//	}
//
//	g_strfreev(elems);
//
//	return table;
//}
//
//char *
//nateon_message_to_string(NateonMessage *msg)
//{
//	size_t body_len;
//	const char *body;
//
//	g_return_val_if_fail(msg != NULL, NULL);
//	g_return_val_if_fail(msg->type == NATEON_MSG_TEXT, NULL);
//
//	body = nateon_message_get_bin_data(msg, &body_len);
//
//	return g_strndup(body, body_len);
//}
//
//void
//nateon_message_show_readable(NateonMessage *msg, const char *info,
//						  gboolean text_body)
//{
//	GString *str;
//	size_t body_len;
//	const char *body;
//	GList *l;
//
//	g_return_if_fail(msg != NULL);
//
//	str = g_string_new(NULL);
//
//	/* Standard header. */
//	if (msg->charset == NULL)
//	{
//		g_string_append_printf(str,
//				   "MIME-Version: 1.0\r\n"
//				   "Content-Type: %s\r\n",
//				   msg->content_type);
//	}
//	else
//	{
//		g_string_append_printf(str,
//				   "MIME-Version: 1.0\r\n"
//				   "Content-Type: %s; charset=%s\r\n",
//				   msg->content_type, msg->charset);
//	}
//
//	for (l = msg->attr_list; l; l = l->next)
//	{
//		char *key;
//		const char *value;
//
//		key = l->data;
//		value = nateon_message_get_attr(msg, key);
//
//		g_string_append_printf(str, "%s: %s\r\n", key, value);
//	}
//
//	g_string_append(str, "\r\n");
//
//	body = nateon_message_get_bin_data(msg, &body_len);
//
//	if (msg->nateonslp_message)
//	{
//		g_string_append_printf(str, "Session ID: %u\r\n", msg->nateonslp_header.session_id);
//		g_string_append_printf(str, "ID:         %u\r\n", msg->nateonslp_header.id);
//		g_string_append_printf(str, "Offset:     %" G_GUINT64_FORMAT "\r\n", msg->nateonslp_header.offset);
//		g_string_append_printf(str, "Total size: %" G_GUINT64_FORMAT "\r\n", msg->nateonslp_header.total_size);
//		g_string_append_printf(str, "Length:     %u\r\n", msg->nateonslp_header.length);
//		g_string_append_printf(str, "Flags:      0x%x\r\n", msg->nateonslp_header.flags);
//		g_string_append_printf(str, "ACK ID:     %u\r\n", msg->nateonslp_header.ack_id);
//		g_string_append_printf(str, "SUB ID:     %u\r\n", msg->nateonslp_header.ack_sub_id);
//		g_string_append_printf(str, "ACK Size:   %" G_GUINT64_FORMAT "\r\n", msg->nateonslp_header.ack_size);
//
//#ifdef NATEON_DEBUG_SLP_VERBOSE
//		if (body != NULL)
//		{
//			if (text_body)
//			{
//				g_string_append_len(str, body, body_len);
//				if (body[body_len - 1] == '\0')
//				{
//					str->len--;
//					g_string_append(str, " 0x00");
//				}
//				g_string_append(str, "\r\n");
//			}
//			else
//			{
//				int i;
//				for (i = 0; i < msg->body_len; i++)
//				{
//					g_string_append_printf(str, "%.2hhX ", body[i]);
//					if ((i % 16) == 15)
//						g_string_append(str, "\r\n");
//				}
//				g_string_append(str, "\r\n");
//			}
//		}
//#endif
//
//		g_string_append_printf(str, "Footer:     %u\r\n", msg->nateonslp_footer.value);
//	}
//	else
//	{
//		if (body != NULL)
//		{
//			g_string_append_len(str, body, body_len);
//			g_string_append(str, "\r\n");
//		}
//	}
//
//	purple_debug_info("nateon", "Message %s:\n{%s}\n", info, str->str);
//
//	g_string_free(str, TRUE);
//}
