/* gbf-project.h
 *
 * Copyright (C) 2002 Jeroen Zwartepoorte
 *
 * 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 of the License, 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 Library 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.
 */

#ifndef _GBF_PROJECT_H_
#define _GBF_PROJECT_H_

#include <glib-object.h>
#include <gtk/gtkwidget.h>

G_BEGIN_DECLS

#define GBF_TYPE_PROJECT		(gbf_project_get_type ())
#define GBF_PROJECT(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GBF_TYPE_PROJECT, GbfProject))
#define GBF_PROJECT_CLASS(obj)		(G_TYPE_CHECK_CLASS_CAST ((klass), GBF_TYPE_PROJECT, GbfProjectClass))
#define GBF_IS_PROJECT(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GBF_TYPE_PROJECT))
#define GBF_IS_PROJECT_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((obj), GBF_TYPE_PROJECT))
#define GBF_PROJECT_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GBF_TYPE_PROJECT, GbfProjectClass))

#define GBF_PROJECT_ERROR		(gbf_project_error_quark ())

#define GBF_TYPE_PROJECT_GROUP          (gbf_project_group_get_type ())
#define GBF_TYPE_PROJECT_TARGET         (gbf_project_target_get_type ())
#define GBF_TYPE_PROJECT_TARGET_SOURCE  (gbf_project_target_source_get_type ())

#define GBF_BUILD_ID_DEFAULT		"DEFAULT"

typedef struct _GbfProject		GbfProject;
typedef struct _GbfProjectClass		GbfProjectClass;
typedef struct _GbfProjectGroup		GbfProjectGroup;
typedef struct _GbfProjectTarget	GbfProjectTarget;
typedef struct _GbfProjectTargetSource	GbfProjectTargetSource;
typedef enum   _GbfProjectError		GbfProjectError;
typedef struct _GbfBuildTarget		GbfBuildTarget;
typedef enum   _GbfBuildType		GbfBuildType;
typedef enum   _GbfBuildMessage		GbfBuildMessage;
typedef struct _GbfBuildWarning		GbfBuildWarning;
typedef struct _GbfBuildError		GbfBuildError;

struct _GbfProjectGroup {
	gchar   *id;
	gchar   *parent_id;

	gchar   *name;

	GList   *groups;
	GList   *targets;
};

struct _GbfProjectTarget {
	gchar   *id;
	gchar   *group_id;

	gchar   *name;
	gchar   *type;

	GList   *sources;
};

struct _GbfProjectTargetSource {
	gchar   *id;
	gchar   *target_id;

	gchar   *source_uri;
};

/* FIXME: extend this list */
enum _GbfProjectError {
	GBF_PROJECT_ERROR_SUCCESS = 0,
	GBF_PROJECT_ERROR_DOESNT_EXIST,
	GBF_PROJECT_ERROR_PROJECT_MALFORMED,
	GBF_PROJECT_ERROR_GENERAL_FAILURE,
};

struct _GbfBuildTarget {
	gchar *id;
	gchar *label;
	gchar *description;
};

enum _GbfBuildMessage {
	GBF_BUILD_START,
	GBF_BUILD_END,
	GBF_BUILD_OUTPUT,
	GBF_BUILD_ERROR,
	GBF_BUILD_WARNING
};

struct _GbfBuildWarning {
	gchar   *filename;
	gint     line;
	gchar   *warning;
	gchar   *output;
};

struct _GbfBuildError {
	gchar   *filename;
	gint     line;
	gchar   *error;
	gchar   *output;
};

typedef void	(* GbfBuildCallback)	(GbfProject     *project,
					 GbfBuildMessage msg,
					 gpointer        data,
					 gpointer        callback_data);

struct _GbfProject {
	GObject parent;
};

struct _GbfProjectClass {
	GObjectClass parent_class;

	/* Signals. */
	void                     (* build_start)           (GbfProject *project);
	void                     (* build_stop)            (GbfProject *project,
							    gboolean    success);
	void                     (* project_updated)       (GbfProject *project);

	/* Virtual Table */
	/* Project. */
	void                     (* load)                  (GbfProject  *project,
							    const gchar *path,
							    GError     **error);
	void                     (* build)                 (GbfProject  *project,
							    const gchar *id,
							    GError     **error);
	void                     (* clean)                 (GbfProject  *project,
							    GError     **error);
	gboolean                 (* probe)                 (GbfProject  *project,
							    const gchar *path,
							    GError     **error);
	void                     (* refresh)               (GbfProject  *project,
							    GError     **error);

	/* Build. */
	GList *                  (* get_build_targets)     (GbfProject       *project,
							    GError          **error);
	void                     (* add_build_callback)    (GbfProject       *project,
							    GbfBuildCallback  callback,
							    gpointer          user_data,
							    GError          **error);
	void                     (* remove_build_callback) (GbfProject       *project,
							    GbfBuildCallback  callback,
							    GError          **error);

	/* Groups. */
	gchar *                  (* add_group)             (GbfProject  *project,
							    const gchar *parent_id,
							    const gchar *name,
							    GError     **error);
	void                     (* remove_group)          (GbfProject  *project,
							    const gchar *id,
							    GError     **error);
	GbfProjectGroup *        (* get_group)             (GbfProject  *project,
							    const gchar *id,
							    GError     **error);
	GList *                  (* get_all_groups)        (GbfProject  *project,
							    GError     **error);
	GtkWidget *              (* configure_group)       (GbfProject  *project,
							    const gchar *id,
							    GError     **error);
	GtkWidget *              (* configure_new_group)   (GbfProject  *project,
							    GError     **error);

	/* Targets. */
	gchar *                  (* add_target)            (GbfProject  *project,
							    const gchar *group_id,
							    const gchar *name,
							    const gchar *type,
							    GError     **error);
	void                     (* remove_target)         (GbfProject  *project,
							    const gchar *id,
							    GError     **error);
	GbfProjectTarget *       (* get_target)            (GbfProject  *project,
							    const gchar *id,
							    GError     **error);
	GList *                  (* get_all_targets)       (GbfProject  *project,
							    GError     **error);
	GtkWidget *              (* configure_target)      (GbfProject  *project,
							    const gchar *id,
							    GError     **error);
	GtkWidget *              (* configure_new_target)  (GbfProject *project,
							    GError     **error);

	/* Sources. */
	gchar *                  (* add_source)            (GbfProject  *project,
							    const gchar *target_id,
							    const gchar *uri,
							    GError     **error);
	void                     (* remove_source)         (GbfProject  *project,
							    const gchar *id,
							    GError     **error);
	GbfProjectTargetSource * (* get_source)            (GbfProject  *project,
							    const gchar *id,
							    GError     **error);
	GList *                  (* get_all_sources)       (GbfProject  *project,
							    GError     **error);
	GtkWidget *              (* configure_source)      (GbfProject  *project,
							    const gchar *id,
							    GError     **error);
	GtkWidget *              (* configure_new_source)  (GbfProject  *project,
							    GError     **error);
	GtkWidget *              (* configure)             (GbfProject  *project,
							    GError     **error);

	/* Types. */
	const gchar *            (* name_for_type)         (GbfProject  *project,
							    const gchar *type);
	const gchar *            (* mimetype_for_type)     (GbfProject  *project,
							    const gchar *type);
	gchar **                 (* get_types)             (GbfProject  *project);
};

GQuark                  gbf_project_error_quark          (void);
GType                   gbf_project_get_type             (void);
GType                   gbf_project_group_get_type       (void);
GType                   gbf_project_target_get_type      (void);
GType                   gbf_project_target_source_get_type (void);
void                    gbf_project_load                 (GbfProject    *project,
							  const gchar   *path,
							  GError       **error);
void                    gbf_project_build                (GbfProject    *project,
							  const gchar   *id,
							  GError       **error);
void                    gbf_project_build_default        (GbfProject    *project,
							  GError       **error);
void                    gbf_project_clean                (GbfProject    *project,
							  GError       **error);
gboolean                gbf_project_probe                (GbfProject    *project,
							  const gchar   *path,
							  GError       **error);
void                    gbf_project_refresh              (GbfProject    *project,
							  GError       **error);

/* Build. */
GList                  *gbf_project_get_build_targets    (GbfProject    *project,
							  GError       **error);
void                    gbf_project_add_build_callback   (GbfProject    *project,
							  GbfBuildCallback callback,
							  gpointer       user_data,
							  GError       **error);
void                    gbf_project_remove_build_callback(GbfProject    *project,
							  GbfBuildCallback callback,
							  GError       **error);

/* Groups. */
gchar                  *gbf_project_add_group            (GbfProject    *project,
							  const gchar   *parent_id,
							  const gchar   *name,
							  GError       **error);
void                    gbf_project_remove_group         (GbfProject    *project,
							  const gchar   *id,
							  GError       **error);
GbfProjectGroup        *gbf_project_get_group            (GbfProject    *project,
							  const gchar   *id,
							  GError       **error);
GList                  *gbf_project_get_all_groups       (GbfProject    *project,
							  GError       **error);
GtkWidget              *gbf_project_configure_group      (GbfProject    *project,
							  const gchar   *id,
							  GError       **error);
GtkWidget              *gbf_project_configure_new_group  (GbfProject    *project,
							  GError       **error);


/* Targets. */
gchar                  *gbf_project_add_target           (GbfProject    *project,
							  const gchar   *group_id,
							  const gchar   *name,
							  const gchar   *type,
							  GError       **error);
void                    gbf_project_remove_target        (GbfProject    *project,
							  const gchar   *id,
							  GError       **error);
GbfProjectTarget       *gbf_project_get_target           (GbfProject    *project,
							  const gchar   *id,
							  GError       **error);
GList                  *gbf_project_get_all_targets      (GbfProject    *project,
							  GError       **error);
GtkWidget              *gbf_project_configure_target     (GbfProject    *project,
							  const gchar   *id,
							  GError       **error);
GtkWidget              *gbf_project_configure_new_target (GbfProject    *project,
							  GError       **error);


/* Sources. */
gchar                  *gbf_project_add_source           (GbfProject    *project,
							  const gchar   *target_id,
							  const gchar   *uri,
							  GError       **error);
void                    gbf_project_remove_source        (GbfProject    *project,
							  const gchar   *id,
							  GError       **error);
GbfProjectTargetSource *gbf_project_get_source           (GbfProject    *project,
							  const gchar   *id,
							  GError       **error);
GList                  *gbf_project_get_all_sources      (GbfProject    *project,
							  GError       **error);
GtkWidget              *gbf_project_configure_source     (GbfProject    *project,
							  const gchar   *id,
							  GError       **error);
GtkWidget              *gbf_project_configure_new_source (GbfProject    *project,
							  GError       **error);
/* Project */

GtkWidget              *gbf_project_configure            (GbfProject *project,
							  GError **error);

/* Types. */
const gchar            *gbf_project_name_for_type        (GbfProject    *project,
							  const gchar   *type);
const gchar            *gbf_project_mimetype_for_type    (GbfProject    *project,
							  const gchar   *type);

gchar                 **gbf_project_get_types            (GbfProject    *project);

/* functions for copying/freeing data structures */

GbfProjectGroup        *gbf_project_group_copy         (GbfProjectGroup        *group);
void                    gbf_project_group_free         (GbfProjectGroup        *group);

GbfProjectTarget       *gbf_project_target_copy        (GbfProjectTarget       *target);
void                    gbf_project_target_free        (GbfProjectTarget       *target);

GbfProjectTargetSource *gbf_project_target_source_copy (GbfProjectTargetSource *source);
void                    gbf_project_target_source_free (GbfProjectTargetSource *source);




#define GBF_BACKEND_BOILERPLATE(class_name, prefix)					\
GType											\
prefix##_get_type (GluePlugin *plugin)							\
{											\
	static GType type = 0;								\
	if (!type) {									\
		static const GTypeInfo type_info = {					\
			sizeof (class_name##Class),					\
			NULL,								\
			NULL,								\
			(GClassInitFunc)prefix##_class_init,				\
			NULL,								\
			NULL,								\
			sizeof (class_name),						\
			0,								\
			(GInstanceInitFunc)prefix##_instance_init			\
		};									\
		if (plugin == NULL) {							\
			type = g_type_register_static (GBF_TYPE_PROJECT,		\
						       #class_name,			\
						       &type_info, 0);			\
		} else {								\
			type = g_type_module_register_type (G_TYPE_MODULE (plugin),	\
							    GBF_TYPE_PROJECT,		\
							    #class_name,		\
							    &type_info, 0);		\
		}									\
	}										\
	return type;									\
}

#define GBF_SIMPLE_BACKEND(class_name, prefix) \
G_MODULE_EXPORT void glue_register_components (GluePlugin *plugin); \
G_MODULE_EXPORT GType glue_get_component_type (GluePlugin *plugin, const gchar *name); \
G_MODULE_EXPORT void \
glue_register_components (GluePlugin *plugin) \
{ \
	prefix##_get_type (plugin); \
} \
G_MODULE_EXPORT GType \
glue_get_component_type (GluePlugin *plugin, const gchar *name) \
{ \
	if (!strcmp (name, #class_name)) { \
		return prefix##_get_type (plugin); \
	} else { \
		return G_TYPE_INVALID;  \
	} \
}

G_END_DECLS

#endif /* _GBF_PROJECT_H_ */
