/*
 * process.c
 * 
 * Copyright (C) 2006  Josef Kufner <jk@myserver.cz>
 * 
 * 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.
 *
 */

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>

#include "main.h"	/* includes loudmouth and glib */
#include "process.h"
#include "message.h"

#define DEBUG 0
#include "debug.h"

static void m_send(LmMessage *m, LmConnection *connection)
{
	static GTimer *timer = NULL;
	const gdouble minimal_delay = 0.35;

	GError *error = NULL;
	gdouble since_last_msg;

	/* prepare anti-flood timer */
	if (!timer)
		timer = g_timer_new();

	/* flood protection */
	since_last_msg = g_timer_elapsed(timer, NULL);
	if (since_last_msg < minimal_delay) {
		usleep((unsigned long)((minimal_delay - since_last_msg) * 1e6));
	}
	g_timer_start(timer);
		
	/* send message */
	if (!lm_connection_send(connection, m, &error)) {
		print_msg(D_ERR, "Failed to send message: '%s'", lm_message_node_to_string(m->node));
		exit(EXIT_FAILURE);
	} else {
		print_msg(D_VERBOSE, "Sent message: '%s'", lm_message_node_to_string(m->node));
	}
}


static void process_stdin_message(MESSAGE *msg, LmConnection *connection)
{
	LmMessage *m;
	LmMessageNode *game, *body;
	char *cmd, *str, *body_text = NULL;

	/* get command */
	if (message_get(msg, MESSAGE_STRING, &cmd, MESSAGE_END)) {
		/* process command */
		switch(cmd[0]) {
			case 'C':
				print_msg(D_DEBUG, "Chat message...");
				if (message_get(msg, MESSAGE_SKIP, MESSAGE_STRING, &str, MESSAGE_END)) {
					/* build message */
					m = lm_message_new_with_sub_type(j_room, LM_MESSAGE_TYPE_MESSAGE, LM_MESSAGE_SUB_TYPE_GROUPCHAT);
					lm_message_node_add_child(m->node, "body", str);

					m_send(m, connection);

					/* clean up */
					lm_message_unref(m);
				}
				break;

			case 'S':
				print_msg(D_DEBUG, "Session control message...");
				
				if (cmd[1] != 'p' || !message_get(msg, MESSAGE_SKIP, MESSAGE_STRING, &body_text, MESSAGE_END)) {
					body_text = NULL;
				}
				
				/* message to string */
				str = message_to_string(msg, 0);

				/* create jabber message */
				m = lm_message_new_with_sub_type(j_room, LM_MESSAGE_TYPE_MESSAGE, LM_MESSAGE_SUB_TYPE_GROUPCHAT);
				game = lm_message_node_add_child(m->node, "game", str);
				lm_message_node_set_attribute(game, "type", "raw");

				/* add copy to body */
				//lm_message_node_add_child(m->node, "body", str);
				//body = lm_message_node_add_child(m->node, "body", NULL);
				body = lm_message_node_add_child(m->node, "body", body_text ? body_text : "--");
				
				/* send message */
				m_send(m, connection);
				lm_message_unref(m);
				free(str);
				
				print_msg(D_DEBUG, "Session control message... sent.");
		}
	}
}


int process_stdin(const char *message, LmConnection *connection)
{
	static MESSAGE *msg;
	static int state = 0;

	GString *token = NULL;
	const char *p;
	char *str;
	
	assert(message != NULL);
	assert(connection != NULL);
	
	for (p = message; *p; p++) {
		if (message_from_stream('N', 0, *p, &state, &token, &msg) == 1) {
			/* debug */
			if (D_DEBUG <= verbose) {
				str = message_to_string(msg, 0);
				print_msg(D_DEBUG, "Received message: %s", str);
				free(str);
			}

			/* process message */
			process_stdin_message(msg, connection);
			message_destroy(msg);
			msg = NULL;
		}
	}
	return 0;
}


int process_message(const LmMessage *message)
{
	LmMessageNode *body = NULL, *game = NULL;
	MESSAGE *msg = NULL;
	const char *from, *p_from, *type, *text;
	char *p_msg_str = NULL;
	int is_remote = 0;

	assert(message != NULL);

	from = lm_message_node_get_attribute(message->node, "from");
	is_remote = (strcmp(from, j_room_complete) != 0);
	print_msg(D_DEBUG, "received message from \"%s\" (local is \"%s\" => remote = %d)", from, j_room_complete, is_remote);

	if (!from)
		return 0;
	
	body = lm_message_node_get_child(message->node, "body");
	game = lm_message_node_get_child(message->node, "game");

	/* game message */
	if (game) {
		print_msg(D_DEBUG, "processing game message part...");
		type = lm_message_node_get_attribute(game, "type");
		if (type && strcmp(type, "raw") == 0) {
			print_msg(D_DEBUG, "Received RAW message.");
			p_msg_str = NULL;
			while ((msg = message_from_string(0, 0, lm_message_node_get_value(game), &p_msg_str))) {
				message_append(msg, 
					MESSAGE_STRING, from,
					MESSAGE_INTEGER, is_remote,
					MESSAGE_END);
				message_to_file(msg, stdout, 0);
				message_destroy(msg);
			}
		}
	}

	/* chat message */
	else if (body) {
		p_from = strchr(from, '/');
		if (p_from)
			p_from++;
		else
			p_from = from;
	
		print_msg(D_DEBUG, "processing chat message part...");
		text = lm_message_node_get_value(body);
		if (text) {
			msg = message_create('N', 'C');
			message_append(msg, MESSAGE_STRING, "C",
					MESSAGE_STRING, text,
					MESSAGE_STRING, p_from,
					MESSAGE_INTEGER, is_remote,
					MESSAGE_END);
			message_to_file(msg, stdout, 0);
			message_destroy(msg);
		}
	}

	print_msg(D_DEBUG, "STDIN message processed.");

	return 1;
}

/* vim:set encoding=utf8: */
