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

/*
 *  Copyright (C) 2006 - 2007 Kouhei Sutou
 *
 *  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 "kz-ext.h"
#include "kz-module.h"

static GList *exts = NULL;
static GList *ext_mods = NULL;

static void kz_ext_base_init (gpointer g_class);

GType
kz_ext_get_type (void)
{
	static GType type = 0;
	if (!type)
	{
		static const GTypeInfo info = {
			sizeof (KzExtIFace),
			kz_ext_base_init, /* 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, "KzExt",
					      &info, 0);
		g_type_interface_add_prerequisite(type,
						  G_TYPE_OBJECT);
	}
	return type;
}

static void
kz_ext_base_init (gpointer g_class)
{
	static gboolean initialized = FALSE;

	if (initialized) return;

	initialized = TRUE;
}

static KzExt *
_kz_ext_new (KzModule *module, const gchar *first_property, ...)
{
	GObject *ext;
	va_list var_args;

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

	return KZ_EXT(ext);
}

void
kz_ext_init (gpointer initial_address)
{
	GList *node;
	const gchar *base_dir;
	base_dir = g_getenv("KZ_EXT_DIR");
	if (!base_dir)
		base_dir = KZ_GET_SYSTEM_EXT_DIR;

	ext_mods = kz_module_load_modules(base_dir);
	for (node = ext_mods; node; node = g_list_next(node))
	{
		KzExt *ext;
		KzModule *module = node->data;

		ext = _kz_ext_new(module,
				  "initial-address", initial_address,
				  NULL);
		exts = g_list_prepend(exts, ext);
	}
}

static void
_kz_ext_setup (KzExt *ext, KzWindow *window)
{
	g_return_if_fail(KZ_IS_EXT(ext));
	g_return_if_fail(KZ_EXT_GET_IFACE(ext)->setup);

	KZ_EXT_GET_IFACE(ext)->setup(ext, window);
}

void
kz_ext_setup (KzWindow *window)
{
	g_list_foreach(exts, (GFunc)_kz_ext_setup, window);
}

void
kz_ext_exit (void)
{
	g_list_foreach(exts, (GFunc)g_object_unref, NULL);
	g_list_free(exts);
	exts = NULL;

	g_list_foreach(ext_mods, (GFunc)kz_module_unload, NULL);
	g_list_free(ext_mods);
	ext_mods = NULL;
}
