#include <stdlib.h> 
#include <string.h>

#include "libisofs.h"
#include "messages.h"

struct libiso_msgs *libiso_messenger = NULL;

int iso_init()
{
	if (libiso_messenger == NULL) {
		if (libiso_msgs_new(&libiso_messenger, 0) <= 0)
			return 0;
	}
	libiso_msgs_set_severities(libiso_messenger, LIBISO_MSGS_SEV_NEVER,
				   LIBISO_MSGS_SEV_FATAL, "libisofs: ", 0);
	return 1;
}

void iso_finish()
{
	libiso_msgs_destroy(&libiso_messenger,0);
}

void iso_msg_debug(char *msg_text)
{
	libiso_msgs_submit(libiso_messenger, -1, 0x00000002,
                       LIBISO_MSGS_SEV_DEBUG, LIBISO_MSGS_PRIO_ZERO, 
                       msg_text, 0, 0);
}

void iso_msg_note(int error_code, char *msg_text)
{
	libiso_msgs_submit(libiso_messenger, -1, error_code,
                       LIBISO_MSGS_SEV_NOTE, LIBISO_MSGS_PRIO_MEDIUM, 
                       msg_text, 0, 0);
}

void iso_msg_hint(int error_code, char *msg_text)
{
	libiso_msgs_submit(libiso_messenger, -1, error_code,
                       LIBISO_MSGS_SEV_HINT, LIBISO_MSGS_PRIO_MEDIUM, 
                       msg_text, 0, 0);
}

void iso_msg_warn(int error_code, char *msg_text)
{
	libiso_msgs_submit(libiso_messenger, -1, error_code,
                       LIBISO_MSGS_SEV_WARNING, LIBISO_MSGS_PRIO_MEDIUM, 
                       msg_text, 0, 0);
}

void iso_msg_sorry(int error_code, char *msg_text)
{
	libiso_msgs_submit(libiso_messenger, -1, error_code,
                       LIBISO_MSGS_SEV_SORRY, LIBISO_MSGS_PRIO_HIGH, 
                       msg_text, 0, 0);
}

void iso_msg_fatal(int error_code, char *msg_text)
{
	libiso_msgs_submit(libiso_messenger, -1, error_code,
                       LIBISO_MSGS_SEV_FATAL, LIBISO_MSGS_PRIO_HIGH, 
                       msg_text, 0, 0);
}

/** 
 * Control queueing and stderr printing of messages from libisofs.
 * Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
 * "NOTE", "UPDATE", "DEBUG", "ALL".
 * 
 * @param queue_severity Gives the minimum limit for messages to be queued.
 *                       Default: "NEVER". If you queue messages then you
 *                       must consume them by iso_msgs_obtain().
 * @param print_severity Does the same for messages to be printed directly
 *                       to stderr.
 * @param print_id       A text prefix to be printed before the message.
 * @return               >0 for success, <=0 for error
 */
int iso_msgs_set_severities(char *queue_severity,
                            char *print_severity, char *print_id)
{
	int ret, queue_sevno, print_sevno;

	ret = libiso_msgs__text_to_sev(queue_severity, &queue_sevno, 0);
	if (ret <= 0)
		return 0;
	ret = libiso_msgs__text_to_sev(print_severity, &print_sevno, 0);
	if (ret <= 0)
		return 0;
	ret = libiso_msgs_set_severities(libiso_messenger, queue_sevno,
					 print_sevno, print_id, 0);
	if (ret <= 0)
		return 0;
	return 1;
}

#define ISO_MSGS_MESSAGE_LEN 4096

/** 
 * Obtain the oldest pending libisofs message from the queue which has at
 * least the given minimum_severity. This message and any older message of
 * lower severity will get discarded from the queue and is then lost forever.
 * 
 * Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
 * "NOTE", "UPDATE", "DEBUG", "ALL". To call with minimum_severity "NEVER"
 * will discard the whole queue.
 * 
 * @param error_code Will become a unique error code as listed in messages.h
 * @param msg_text   Must provide at least ISO_MSGS_MESSAGE_LEN bytes.
 * @param os_errno   Will become the eventual errno related to the message
 * @param severity   Will become the severity related to the message and
 *                   should provide at least 80 bytes.
 * @return 1 if a matching item was found, 0 if not, <0 for severe errors
 */
int iso_msgs_obtain(char *minimum_severity,
                     int *error_code, char msg_text[], int *os_errno,
                     char severity[])
{
	int ret, minimum_sevno, sevno, priority;
	char *textpt, *sev_name;
	struct libiso_msgs_item *item = NULL;

	if (libiso_messenger == NULL)
		return 0;

	ret = libiso_msgs__text_to_sev(minimum_severity, &minimum_sevno, 0);
	if (ret <= 0)
		return 0;
	ret = libiso_msgs_obtain(libiso_messenger, &item, minimum_sevno,
				LIBISO_MSGS_PRIO_ZERO, 0);
	if (ret <= 0)
		goto ex;
	ret = libiso_msgs_item_get_msg(item, error_code, &textpt, os_errno, 0);
	if (ret <= 0)
		goto ex;
	strncpy(msg_text, textpt, ISO_MSGS_MESSAGE_LEN-1);
	if(strlen(textpt) >= ISO_MSGS_MESSAGE_LEN)
		msg_text[ISO_MSGS_MESSAGE_LEN-1] = 0;

	severity[0]= 0;
	ret = libiso_msgs_item_get_rank(item, &sevno, &priority, 0);
	if(ret <= 0)
		goto ex;
	ret = libiso_msgs__sev_to_text(sevno, &sev_name, 0);
	if(ret <= 0)
		goto ex;
	strcpy(severity,sev_name);

	ret = 1;
ex:
	libiso_msgs_destroy_item(libiso_messenger, &item, 0);
	return ret;
}

void *iso_get_messenger(void)
{
	return libiso_messenger;
}