/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2007 Kouhei Sutou <kou@cozmixng.org>
 *  Copyright (C) 2004 Hiroyuki Ikezoe
 *
 *  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, 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.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <glib/gi18n.h>
#include <gmodule.h>

#include "kazehakase.h"
#include "glib-utils.h"
#include "kz-search.h"
#include "kz-module.h"


static GList *searches = NULL;

static const gchar *
_kz_search_module_dir (void)
{
	const gchar *base_dir;
        base_dir = g_getenv("KZ_SEARCH_MODULE_DIR");
	if (base_dir)
		return base_dir;
        return KZ_GET_SYSTEM_SEARCH_MODULE_DIR;
}

void
kz_search_load (const gchar *base_dir)
{
	if (!base_dir)
		base_dir = _kz_search_module_dir();

	searches = g_list_concat(kz_module_load_modules(base_dir), searches);
}

void
kz_search_unload (void)
{
	g_list_foreach(searches, (GFunc)kz_module_unload, NULL);
	g_list_free(searches);
	searches = NULL;
}

void
kz_search_exit (void)
{
	g_list_foreach(searches, (GFunc)kz_module_exit, NULL);
}

GList *
kz_search_engine_names (void)
{
	GList *node;
	GList *result = NULL;

	if (!searches)
		kz_search_load(NULL);

	for (node = searches; node; node = g_list_next(node))
	{
		KzModule *module = node->data;
		result = g_list_append(result,
				       g_strdup(kz_module_get_name(module)));
	}

	return result;
}

GList *
kz_search_engine_ids (void)
{
	GList *node;
	GList *result = NULL;

	if (!searches)
		kz_search_load(NULL);

	for (node = searches; node; node = g_list_next(node))
	{
		KzModule *module = node->data;
		result = g_list_append(result,
				       g_strdup(G_TYPE_MODULE(module)->name));
	}

	return result;
}

static KzSearch *
_kz_search_new (KzModule *module, const gchar *name,
	       const gchar *first_property, ...)
{
	GObject *search;
	va_list var_args;

	va_start(var_args, first_property);
	search = kz_module_instantiate(module, first_property, var_args);
	va_end(var_args);

	return KZ_SEARCH(search);
}

KzSearch *
kz_search_new (const gchar *name)
{
	KzModule *module;

	module = kz_module_find(searches, name);
	if (!module)
	{
		module = kz_module_load_module(_kz_search_module_dir(), name);
		if (!module)
			return NULL;
		searches = g_list_prepend(searches, module);
	}

	return _kz_search_new(module, name, NULL);
}


GType
kz_search_get_type (void)
{
	static GType type = 0;
	if (!type)
	{
		static const GTypeInfo info = {
			sizeof (KzSearchIFace),
			NULL,               /* base_init */
			NULL,               /* base_finalize */
			NULL,               /* class_init */
			NULL,               /* class_finalize */
			NULL,               /* class_data */
			0,
			0,                  /* n_preallocs */
			NULL,               /* instance_init */
		};
		type = g_type_register_static(G_TYPE_INTERFACE, "KzSearch",
					      &info, 0);
		g_type_interface_add_prerequisite(type, G_TYPE_OBJECT);
	}
	return type;
}

gchar *
kz_search_get_search_result_html (KzSearch *search, const gchar *text)
{
	KzSearchIFace *iface;

	g_return_val_if_fail(KZ_IS_SEARCH(search), NULL);

	iface = KZ_SEARCH_GET_IFACE(search);
	g_return_val_if_fail(iface->get_search_result_html, NULL);

	return iface->get_search_result_html(search, text);
}

KzBookmark *
kz_search_get_search_result_bookmark (KzSearch *search, const gchar *text)
{
	KzSearchIFace *iface;

	g_return_val_if_fail(KZ_IS_SEARCH(search), NULL);

	iface = KZ_SEARCH_GET_IFACE(search);
	g_return_val_if_fail(iface->get_search_result_bookmark, NULL);

	return iface->get_search_result_bookmark(search, text);
}

gboolean
kz_search_register_document (KzSearch *search, const gchar *uri,
			     const gchar *title, const gchar *contents,
			     GTime mtime)
{
	KzSearchIFace *iface;

	g_return_val_if_fail(KZ_IS_SEARCH(search), FALSE);

	iface = KZ_SEARCH_GET_IFACE(search);
	g_return_val_if_fail(iface->register_document, FALSE);

	return iface->register_document(search, uri, title, contents, mtime);
}

gboolean
kz_search_unregister_document (KzSearch *search, const gchar *uri)
{
	KzSearchIFace *iface;

	g_return_val_if_fail(KZ_IS_SEARCH(search), FALSE);

	iface = KZ_SEARCH_GET_IFACE(search);
	g_return_val_if_fail(iface->unregister_document, FALSE);

	return iface->unregister_document(search, uri);
}

GPid
kz_search_optimize_index (KzSearch *search)
{
	KzSearchIFace *iface;

	g_return_val_if_fail(KZ_IS_SEARCH(search), 0);

	iface = KZ_SEARCH_GET_IFACE(search);
	g_return_val_if_fail(iface->optimize_index, 0);

	return iface->optimize_index(search);
}

void
kz_search_make_index (KzSearch *search)
{
	KzSearchIFace *iface;

	g_return_if_fail(KZ_IS_SEARCH(search));

	iface = KZ_SEARCH_GET_IFACE(search);
	g_return_if_fail(iface->make_index);

	return iface->make_index(search);
}

gboolean
kz_search_exist_index_dir (KzSearch *search)
{
	KzSearchIFace *iface;

	g_return_val_if_fail(KZ_IS_SEARCH(search), FALSE);

	iface = KZ_SEARCH_GET_IFACE(search);
	g_return_val_if_fail(iface->make_index, FALSE);

	return iface->exist_index_dir(search);
}

