/*
 * 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 process_stdin_message(MESSAGE *msg, LmConnection *connection)
{
	LmMessage *m;
	LmMessageNode *game, *body;
	char *cmd, *str, *cat, *mod, *opt, *body_text = NULL;
	gchar *tmpstr;
	struct s_opt_query *p_opt = NULL;

	/* get command */
	if (message_get(msg, MESSAGE_PART_DATA, MESSAGE_STRING, &cmd, MESSAGE_END)) {
		/* process command */
		switch(cmd[0]) {
			case 'C':
				print_msg(D_DEBUG, "Chat message...");
				if (message_get(msg, MESSAGE_PART_DATA, 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] != 't' && cmd[1] != 'c' && cmd[1] != 'q' && cmd[1] != 'i')
						|| !message_get(msg, MESSAGE_PART_DATA, 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);
				tmpstr = g_strdup_printf("# %s", body_text ? body_text : "--");
				body = lm_message_node_add_child(m->node, "body", tmpstr);
				g_free(tmpstr);
				
				/* send message */
				m_send(m, connection);
				lm_message_unref(m);
				free(str);
				
				print_msg(D_DEBUG, "Session control message... sent.");
				break;

			case 'O':
				if (!connection && cmd[1] == 'r' && message_get(msg, MESSAGE_PART_DATA, MESSAGE_SKIP, MESSAGE_STRING, &cat,
							MESSAGE_STRING, &mod, MESSAGE_STRING, &opt, MESSAGE_END))
				{
					int int_val = 0;
					char *str_val = NULL;
					int can_connect_now = 1;
					
					/* find pointer to value */
					for (p_opt = opt_query; p_opt->opt; p_opt++) {
						if (strcmp(p_opt->opt, opt) == 0) {
							break;
						}
						if (!p_opt->received)
							can_connect_now = 0;
					}
					
					//print_msg(D_DEBUG, "Received option %s ...", opt);

					/* store option */
					if (p_opt && p_opt->type == MESSAGE_STRING) {
						if (message_get(msg, MESSAGE_PART_DATA, MESSAGE_SKIP, MESSAGE_SKIP, MESSAGE_SKIP, MESSAGE_SKIP,
									MESSAGE_STRING, &str_val, MESSAGE_END))
						{
							*((char **)(p_opt->var)) = strdup(str_val);
							print_msg(D_DEBUG, "Received option %s = \"%s\"", opt, str_val);
						}
						p_opt->received = 1;
					} else if (p_opt && p_opt->type == MESSAGE_INTEGER) {
						if (message_get(msg, MESSAGE_PART_DATA, MESSAGE_SKIP, MESSAGE_SKIP, MESSAGE_SKIP, MESSAGE_SKIP,
									MESSAGE_INTEGER, &int_val, MESSAGE_END))
						{
							*((int *)(p_opt->var)) = int_val;
							print_msg(D_DEBUG, "Received option %s = %d", opt, int_val);
						}
						p_opt->received = 1;
					} else {
						can_connect_now = 0;
					}
					
					/* check rest */
					for (; can_connect_now && p_opt && p_opt->opt; p_opt++) {
						if (!p_opt->received)
							can_connect_now = 0;
					}
					
					//print_msg(D_DEBUG, "Received option %s = \"%s\", %d", opt, str_val, int_val);

					/* connect */
					if (can_connect_now) {
						print_msg(D_DEBUG, "Received all requested options.");
						open_connection();
					}
				}
			case 'T':
				switch (cmd[1]) {
					case 'p': /* ping */
						{
							MESSAGE *msg;
							DBG_MSG(3, "Ping.");
							msg = message_create(0, 0);
							message_append(msg, MESSAGE_PART_DATA, 
								MESSAGE_STRING, "Tr",
								MESSAGE_END);
							message_to_file(msg, stdout, 0);
							message_destroy(msg);
						}
						break;
				}
		}
	}
}


int process_stdin(const char *message, LmConnection *connection)
{
	static MESSAGE *msg;
	const char *p;
	char *str;
	
	assert(message != NULL);
	
	print_msg(D_DEBUG, "Parsing data...");
	for (p = message; *p; p++) {
		if (message_from_stream('N', 0, *p, &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, int is_old)
{
	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) {
		if (!is_old) {
			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_destroy_part(msg, MESSAGE_PART_SENDER_INFO);
					message_append(msg, MESSAGE_PART_SENDER_INFO, 
						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_PART_DATA, MESSAGE_STRING, "C",
					MESSAGE_STRING, text,
					MESSAGE_END);
			message_append(msg, MESSAGE_PART_SENDER_INFO,
					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: */
