/*
 * Copyright (C) 2011-2012 Red Hat, Inc.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU Lesser General Public License v.2.1.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#define _REENTRANT

#include "tool.h"

#include "daemon-server.h"
#include "daemon-log.h"

#include <syslog.h>

struct backend {
	int id;
	void (*log)(log_state *s, void **state, int type, const char *message);
};

static void log_syslog(log_state *s, void **state, int type, const char *message)
{
	int prio;

	if (!*state) { /* initialize */
		*state = (void *)1;
		openlog(s->name, LOG_PID, LOG_DAEMON);
	}

	switch (type) {
	case DAEMON_LOG_INFO: prio = LOG_INFO; break;
	case DAEMON_LOG_WARN: prio = LOG_WARNING; break;
	case DAEMON_LOG_ERROR: prio = LOG_ERR; break;
	case DAEMON_LOG_FATAL: prio = LOG_CRIT; break;
	default: prio = LOG_DEBUG; break;
	}

	syslog(prio, "%s", message);
}

static void log_stderr(log_state *s, void **state, int type, const char *message)
{
	const char *prefix;

	switch (type) {
	case DAEMON_LOG_INFO: prefix = "I: "; break;
	case DAEMON_LOG_WARN: prefix = "W: " ; break;
	case DAEMON_LOG_ERROR: /* fall through */
	case DAEMON_LOG_FATAL: prefix = "E: " ; break;
	default: prefix = ""; break;
	}

	fprintf(stderr, "%s%s\n", prefix, message);
}

struct backend backend[] = {
	{ DAEMON_LOG_OUTLET_SYSLOG, log_syslog },
	{ DAEMON_LOG_OUTLET_STDERR, log_stderr },
	{ 0, 0 }
};

void daemon_log(log_state *s, int type, const char *message) {
	int i = 0;
	while ( backend[i].id ) {
		if ((int)(s->log_config[type] & backend[i].id) == backend[i].id )
			backend[i].log( s, &s->backend_state[i], type, message );
		++ i;
	}
}

static int _type_interesting(log_state *s, int type) {
	int i = 0;
	while ( backend[i].id ) {
		if ((int)(s->log_config[type] & backend[i].id) == backend[i].id )
			return 1;
		++ i;
	}
	return 0;
}

void daemon_logf(log_state *s, int type, const char *fmt, ...) {
	char *buf;
	va_list ap;

	va_start(ap, fmt);
	if (dm_vasprintf(&buf, fmt, ap) >= 0) {
		daemon_log(s, type, buf);
		dm_free(buf);
	} /* else return_0 */
	va_end(ap);
}

struct log_line_baton {
	log_state *s;
	int type;
	const char *prefix;
};

static int _log_line(const char *line, void *baton) {
	struct log_line_baton *b = baton;
	daemon_logf(b->s, b->type, "%s%s", b->prefix, line);
	return 0;
}

void daemon_log_cft(log_state *s, int type, const char *prefix, const struct dm_config_node *n)
{
	struct log_line_baton b = { .s = s, .type = type, .prefix = prefix };

	if (!_type_interesting(s, type))
		return;

	(void) dm_config_write_node(n, &_log_line, &b);
}

void daemon_log_multi(log_state *s, int type, const char *prefix, const char *msg)
{
	struct log_line_baton b = { .s = s, .type = type, .prefix = prefix };
	char *buf;
	char *pos;

	if (!_type_interesting(s, type))
		return;

	buf = dm_strdup(msg);
	pos = buf;

	if (!buf)
		return; /* _0 */

	while (pos) {
		char *next = strchr(pos, '\n');
		if (next)
			*next = 0;
		_log_line(pos, &b);
		pos = next ? next + 1 : 0;
	}
	dm_free(buf);
}

void daemon_log_enable(log_state *s, int outlet, int type, int enable)
{
	if (type >= 32)
		return;

	if (enable)
		s->log_config[type] |= outlet;
	else
		s->log_config[type] &= ~outlet;
}

static int _parse_one(log_state *s, int outlet, const char *type, int enable)
{
	int i;
	if (!strcmp(type, "all"))
		for (i = 0; i < 32; ++i)
			daemon_log_enable(s, outlet, i, enable);
	else if (!strcmp(type, "fatal"))
		daemon_log_enable(s, outlet, DAEMON_LOG_FATAL, enable);
	else if (!strcmp(type, "error"))
		daemon_log_enable(s, outlet, DAEMON_LOG_ERROR, enable);
	else if (!strcmp(type, "warn"))
		daemon_log_enable(s, outlet, DAEMON_LOG_WARN, enable);
	else if (!strcmp(type, "info"))
		daemon_log_enable(s, outlet, DAEMON_LOG_INFO, enable);
	else if (!strcmp(type, "wire"))
		daemon_log_enable(s, outlet, DAEMON_LOG_WIRE, enable);
	else if (!strcmp(type, "debug"))
		daemon_log_enable(s, outlet, DAEMON_LOG_DEBUG, enable);

	return 1;
}

int daemon_log_parse(log_state *s, int outlet, const char *types, int enable)
{
	char *buf;
	char *pos;

	if (!types || !types[0])
		return 1;

	if (!(buf = dm_strdup(types)))
		return 0;

	pos = buf;
	while (pos) {
		char *next = strchr(pos, ',');
		if (next)
			*next = 0;
		if (!_parse_one(s, outlet, pos, enable)) {
			dm_free(buf);
			return 0;
		}
		pos = next ? next + 1 : 0;
	}

	dm_free(buf);

	return 1;
}
