/*
 * Galago Base Object
 *
 * Copyright (C) 2004-2006 Christian Hammond
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 */
#ifndef _GALAGO_OBJECT_H_
#define _GALAGO_OBJECT_H_

#include <glib.h>
#include <glib-object.h>

#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>

typedef struct _GalagoObjectClass   GalagoObjectClass;
typedef struct _GalagoObject        GalagoObject;
typedef struct _GalagoObjectPrivate GalagoObjectPrivate;

struct _GalagoObject
{
	GObject parent_object;
	guint32 flags;

	GalagoObjectPrivate *priv;

	void (*reserved_1)(void);
	void (*reserved_2)(void);
	void (*reserved_3)(void);
	void (*reserved_4)(void);
};

struct _GalagoObjectClass
{
	GObjectClass parent_class;

	const char *dbus_interface;
	const char *dbus_signature;
	gboolean supports_attrs;

	/* Virtual functions */
	void (*dbus_message_append)(DBusMessageIter *iter,
								const GalagoObject *object);
	void *(*dbus_message_get)(DBusMessageIter *iter);
	void (*dbus_push_full)(GalagoObject *object);
	gchar *(*dbus_get_signature)(void);
	void (*set_attribute)(GalagoObject *object, const char *name,
						  GValue *value);
	gboolean (*remove_attribute)(GalagoObject *object, const char *name);
	const GValue *(*get_attribute)(const GalagoObject *object,
								   const char *name);
	GList *(*get_attributes)(const GalagoObject *object);

	/* Signals */
	void (*destroy)(GalagoObject *object);

	void (*reserved_1)(void);
	void (*reserved_2)(void);
	void (*reserved_3)(void);
	void (*reserved_4)(void);
};

#define GALAGO_TYPE_OBJECT (galago_object_get_type())

/** Cast @c obj to a GalagoObject. */
#define GALAGO_OBJECT(obj) \
		(G_TYPE_CHECK_INSTANCE_CAST((obj), GALAGO_TYPE_OBJECT, GalagoObject))
#define GALAGO_OBJECT_CLASS(klass) \
		(G_TYPE_CHECK_CLASS_CAST((klass), GALAGO_TYPE_OBJECT, \
								 GalagoObjectClass))
#define GALAGO_IS_OBJECT(obj) \
		(G_TYPE_CHECK_INSTANCE_TYPE((obj), GALAGO_TYPE_OBJECT))
#define GALAGO_IS_OBJECT_CLASS(klass) \
		(G_TYPE_CHECK_CLASS_TYPE((klass), GALAGO_TYPE_OBJECT))
#define GALAGO_OBJECT_GET_CLASS(obj) \
		(G_TYPE_INSTANCE_GET_CLASS((obj), GALAGO_TYPE_OBJECT, \
								   GalagoObjectClass))

typedef enum
{
	GALAGO_OBJECT_IN_DESTRUCTION = 1,
	GALAGO_OBJECT_RESERVED_1     = 2,
	GALAGO_OBJECT_RESERVED_2     = 4

} GalagoObjectFlags;

#define GALAGO_OBJECT_HAS_FLAG(obj, flag) \
	((GALAGO_OBJECT_FLAGS(obj) & (flag)) == (flag))
#define GALAGO_OBJECT_FLAGS(obj) (GALAGO_OBJECT(obj)->flags)
#define GALAGO_OBJECT_SET_FLAGS(obj, flag) \
	G_STMT_START{ (GALAGO_OBJECT_FLAGS(obj) |= (flag)); } G_STMT_END
#define GALAGO_OBJECT_UNSET_FLAGS(obj, flag) \
	G_STMT_START{ (GALAGO_OBJECT_FLAGS(obj) &= ~(flag)); } G_STMT_END


typedef enum
{
	GALAGO_LOCAL = 0,
	GALAGO_REMOTE

} GalagoOrigin;

#define GALAGO_ORIGIN_IS_VALID(origin) \
	((origin) == GALAGO_LOCAL || (origin) == GALAGO_REMOTE)

#define GALAGO_OBJECT_IS_LOCAL(obj) \
	(galago_object_get_origin(GALAGO_OBJECT(obj)) == GALAGO_LOCAL)
#define GALAGO_OBJECT_IS_REMOTE(obj) \
	(galago_object_get_origin(GALAGO_OBJECT(obj)) == GALAGO_REMOTE)

typedef guint GalagoCallHandle;
#define GALAGO_CALL_HANDLE_INVALID ((GalagoCallHandle)0)

#include <libgalago/galago-context-base.h>

G_BEGIN_DECLS

GType galago_object_get_type(void);

void galago_object_destroy(GalagoObject *object);

const gchar *galago_object_type_get_dbus_signature(GType type);

void galago_object_set_dbus_path(GalagoObject *object, const gchar *obj_path);
const gchar *galago_object_get_dbus_path(const GalagoObject *object);

void galago_object_set_watch(GalagoObject *object, gboolean watch);
gboolean galago_object_is_watched(const GalagoObject *object);

GalagoOrigin galago_object_get_origin(const GalagoObject *object);
GalagoContext *galago_object_get_context(const GalagoObject *object);

void galago_object_set_attr_string(GalagoObject *object, const char *name,
								   const char *value);
void galago_object_set_attr_bool(GalagoObject *object, const char *name,
								 gboolean value);
void galago_object_set_attr_int(GalagoObject *object, const char *name,
								gint32 value);
void galago_object_set_attr_double(GalagoObject *object, const char *name,
								   gdouble value);
void galago_object_set_attribute(GalagoObject *object, const char *name,
								 GValue *value);
gboolean galago_object_remove_attribute(GalagoObject *object,
										const char *name);
const char *galago_object_get_attr_string(const GalagoObject *object,
										  const char *name);
gboolean galago_object_get_attr_bool(const GalagoObject *object,
									 const char *name);
gint32 galago_object_get_attr_int(const GalagoObject *object,
								  const char *name);
gdouble galago_object_get_attr_double(const GalagoObject *object,
									  const char *name);
const GValue *galago_object_get_attribute(const GalagoObject *object,
										  const char *name);
gboolean galago_object_get_has_attribute(const GalagoObject *object,
										 const char *name);
GList *galago_object_get_attributes(const GalagoObject *object);

G_END_DECLS

#endif /* _GALAGO_OBJECT_H_ */
