/*
 * message.h
 * 
 * Copyright (C) 2006-2007  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.
 *
 */
#ifndef JK_MESSAGE_H
#define JK_MESSAGE_H

#include <glib.h>
#include <stdio.h>

#define MESSAGE_MAX_TARGETS	127

typedef enum {
	MESSAGE_PART_DATA,
	MESSAGE_PART_SENDER_INFO,
	MESSAGE_PART_EXTRA,
	MESSAGE_PART_MAX
} MESSAGE_PART_ID;

typedef enum {
	MESSAGE_END,
	MESSAGE_INTEGER,
	MESSAGE_STRING,
	MESSAGE_SKIP
} MESSAGE_ITEM_TYPE;


struct s_message_item {
	MESSAGE_ITEM_TYPE type;
	union {
		long integer;
		char *string;
	} value;
	struct s_message_item *next;
};

typedef struct {
	struct s_message_item *list, *p_list_end, *p_list_next;
	int length;
} MESSAGE_PART;

typedef struct {
	/* header */
	char src, dest;
	
	/* message data */
	MESSAGE_PART part[MESSAGE_PART_MAX];

	/* for message_from_stream() */
	int state, cur_part;
	GString *token;
} MESSAGE;


typedef void (*MESSAGE_HANDLER)(MESSAGE *);

/* message infrastructure initialization */
void message_init(void);
	
/* create empty message */
MESSAGE *message_create(char src, char dest);
	
/* destroy message */
void message_destroy_part(MESSAGE *msg, MESSAGE_PART_ID part_id);
void message_destroy(MESSAGE *msg);

/* modify src and/or dest (zero = don't change) */
void message_edit(MESSAGE *msg, char src, char dest);

/* append data into message */
int message_append(MESSAGE *msg, MESSAGE_PART_ID part, MESSAGE_ITEM_TYPE first_item, ...);

/* get data from message
 *
 * simple example -- get everything in one shot:
 * 
 * 	message_get(msg, part, type, &var, type, &var, ..., MESSAGE_END);
 *
 * 
 * another example -- get items in loop:
 * 
 * 	message_get_rewind(msg, part);
 * 	while (message_get_next(msg, part, type, &var, type, &var, ..., MESSAGE_END)) {
 *		...
 * 	}
 *
 */
int message_get_from(MESSAGE *msg, int part, int get_next, MESSAGE_ITEM_TYPE first_item, ...);
#define message_get(msg,part,args...) message_get_from((msg), (part), 0, ##args)
#define message_get_next(msg,part,args...) message_get_from((msg), (part), 1, ##args)
void message_get_rewind(MESSAGE *msg, MESSAGE_PART_ID part);

/* create message from string */
MESSAGE *message_from_string(char src, char dest, const char *str, char **p);

/* create message from stream of chars, see message_from_string for details */
int message_from_stream(char src, char dest, char ch, MESSAGE **msg);

/* convert message to string */
char *message_to_string(MESSAGE *msg, int append_nl);

/* stream message to file */
int message_to_file(MESSAGE *msg, FILE *file, int append_nl);

/* send message */
int message_send(MESSAGE *msg);

/* register target for messages (callback) */
int message_register_target(char dest, MESSAGE_HANDLER handler, const char *description);
int message_unregister_target(char dest);

/* info about target */
const char *message_get_target_description(char target);
	
/* get all target ids */
typedef int MESSAGE_GET_TARGET_ITER;
void message_get_target_id_rewind (MESSAGE_GET_TARGET_ITER *iter);
int message_get_target_id_next (MESSAGE_GET_TARGET_ITER *iter);

#endif

