/*
 * dsyslog - a dumb syslog (e.g. syslog for people who have a clue)
 * Copyright (c) 2008 William Pitcock <nenolod@sacredspiral.co.uk>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "dsyslog.h"

struct dsyslog_cond_type_map {
        gchar *type;
        dsyslog_cond_eval_t hdl;
};

static GList *cond_type_list_ = NULL;

GList *
dsyslog_cond_add(GList *conditions, dsyslog_cond_t *cond)
{
	GList *n;

	_ENTER;

	for (n = cond_type_list_; n != NULL; n = g_list_next(n)) {
		struct dsyslog_cond_type_map *m = (struct dsyslog_cond_type_map *) n->data;

		if (!g_ascii_strcasecmp(m->type, cond->type)) {
			cond->evaluator = m->hdl;
			break;
		}
	}

	conditions = g_list_append(conditions, cond);
	dsyslog_perfctr.conds++;

	_LEAVE conditions;
}

GList *
dsyslog_cond_remove(GList *conditions, dsyslog_cond_t *cond)
{
	_ENTER;

	conditions = g_list_remove_all(conditions, cond);

	if (cond->destructor)
		cond->destructor(cond);

	g_free(cond->type);
	g_free(cond->cond);
	g_free(cond->value);
	g_slice_free(dsyslog_cond_t, cond);

	dsyslog_perfctr.conds--;

	_LEAVE conditions;
}

void
dsyslog_cond_type_register(gchar *type, dsyslog_cond_eval_t hdl)
{
	struct dsyslog_cond_type_map *m;

	_ENTER;

	m = g_slice_new(struct dsyslog_cond_type_map);
	m->type = type;
	m->hdl = hdl;

	cond_type_list_ = g_list_prepend(cond_type_list_, m);

	_LEAVE;
}

void
dsyslog_cond_type_unregister(gchar *type)
{
	GList *n;

	_ENTER;

	for (n = cond_type_list_; n != NULL; n = g_list_next(n)) {
		struct dsyslog_cond_type_map *m = (struct dsyslog_cond_type_map *) n->data;

		if (!g_ascii_strcasecmp(type, m->type)) {
			cond_type_list_ = g_list_remove_all(cond_type_list_, m);
			g_slice_free(struct dsyslog_cond_type_map, m);

			_LEAVE;
		}
	}

	_LEAVE;
}

gboolean
dsyslog_cond_process(dsyslog_event_t *event, GList *conditions)
{
	GList *n;
	gboolean ret = FALSE, ret2;

	_ENTER;

	_DEBUG("conditions length %d", g_list_length(conditions));
	if (g_list_length(conditions) == 0) {
		ret = TRUE;
	}

	for (n = conditions; n != NULL; n = g_list_next(n)) {
		dsyslog_cond_t *cond = (dsyslog_cond_t *) n->data;
		ret2 = cond->evaluator(event, cond);
		_DEBUG("ret2(%d)", ret2);

		if (ret2)
			ret = TRUE;
	}

	_DEBUG("ret(%d)", ret);

	_LEAVE ret;
}
