/* sunone-permissions-dialog.c
 *
 * Copyright (C) 2002-2004 Sun Microsystems, Inc
 *
 * AUTHORS
 *     Jack Jia <jack.jia@sun.com>
 *     Harry Lu <harry.lu@sun.com>
 *     Alfred Peng <alfred.peng@sun.com>
 *     Rodrigo Moya <rodrigo@ximian.com>
 *
 */

#include "sunone-i18n.h"
#include <string.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <e-util/e-dialog-utils.h>
#include "lib/sunone-ace.h"
#include "sunone-add-permission-dialog.h"
#include "sunone-permissions-dialog.h"

struct _SunOnePermissionsDialogPrivate {
	SunOneConnection *cnc;
	gchar *calid;
	SunOneCalendarProperties *calprops;
	GladeXML *xml;
	GtkWidget *main_table;

	GtkTreeView *perm_tree;
	GtkWidget *add_button;
	GtkWidget *edit_button;
	GtkWidget *remove_button;

	GtkTreeView *owners_tree;
	GtkWidget *owners_add_button;
	GtkWidget *owners_remove_button;
};

static void sunone_permissions_dialog_class_init (SunOnePermissionsDialogClass *klass);
static void sunone_permissions_dialog_init (SunOnePermissionsDialog *object);
static void sunone_permissions_dialog_dispose (GObject *object);
static void sunone_permissions_dialog_finalize (GObject *object);

enum PermissionCols {
	NAME_COL,
	AVAILABILITY_COL,
	INVITE_COL,
	READ_COL,
	DELETE_COL,
	MODIFY_COL,
	LAST_PERMISSION_COL
};

static GObjectClass *parent_class = NULL;

static void
sunone_permissions_dialog_class_init (SunOnePermissionsDialogClass *klass)
{
	GObjectClass *object_class = G_OBJECT_CLASS (klass);

	parent_class = g_type_class_ref (GTK_TYPE_DIALOG);

	object_class->dispose = sunone_permissions_dialog_dispose;
	object_class->finalize = sunone_permissions_dialog_finalize;
}

static void
manage_ace (SunOnePermissionsDialog *dialog, SunOneACE *ace)
{
	GtkWidget *gdialog;

	g_return_if_fail (IS_SUNONE_PERMISSIONS_DIALOG (dialog));
	gdialog = sunone_add_permission_dialog_new (dialog, ace);
}

static void
add_permission_cb (GtkButton *button, gpointer user_data)
{
	manage_ace (SUNONE_PERMISSIONS_DIALOG (user_data), NULL);
}

static void
edit_permission_cb (GtkButton *button, gpointer user_data)
{
	SunOnePermissionsDialog *dialog = SUNONE_PERMISSIONS_DIALOG (user_data);
	SunOnePermissionsDialogPrivate *priv = dialog->priv;
	SunOneACE *ace;
	gint row;
	GList *l;
	GtkTreeSelection * selection;
	GtkTreeModel *model;
	GtkTreePath *path;
	GtkTreeIter iter;

	g_return_if_fail (IS_SUNONE_PERMISSIONS_DIALOG (dialog));

	selection = gtk_tree_view_get_selection (priv->perm_tree);
	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
		return;

	path = gtk_tree_model_get_path (model, &iter);
	row = gtk_tree_path_get_indices (path)[0];
	gtk_tree_path_free (path);

	g_return_if_fail (row >= 0 && row < g_list_length (dialog->merged_acls));

	l = g_list_nth (dialog->merged_acls, row);
	if (!l)
		return;

	ace = SUNONE_ACE (l->data);
	manage_ace (dialog, ace);
}

static void
remove_permission_cb (GtkButton *button, gpointer user_data)
{
	SunOnePermissionsDialog *dialog = SUNONE_PERMISSIONS_DIALOG (user_data);
	SunOnePermissionsDialogPrivate *priv = dialog->priv;
	int row;
	GList *l;
	GtkTreeSelection * selection;
	GtkTreeModel *model;
	GtkTreePath *path;
	GtkTreeIter iter;

	SunOneACE *ace;

	g_return_if_fail (IS_SUNONE_PERMISSIONS_DIALOG (dialog));

	selection = gtk_tree_view_get_selection (priv->perm_tree);
	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
		return;

	path = gtk_tree_model_get_path (model, &iter);
	row = gtk_tree_path_get_indices (path)[0];
	gtk_tree_path_free (path);

	g_return_if_fail (row >= 0 && row < g_list_length (dialog->merged_acls));

	l = g_list_nth (dialog->merged_acls, row);
	if (!l)
		return;

	gtk_list_store_remove ((GtkListStore *) model, &iter);

	/* remove the ACE from our list */
	ace = SUNONE_ACE (l->data);
	dialog->merged_acls = g_list_remove_link (dialog->merged_acls, l);
	g_object_unref (G_OBJECT (ace));

	gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
}

static void
permission_selection_changed_cb (GtkTreeSelection *selection, gpointer user_data)
{
	SunOnePermissionsDialog *dialog = SUNONE_PERMISSIONS_DIALOG (user_data);
	SunOnePermissionsDialogPrivate *priv = dialog->priv;

	if (gtk_tree_selection_get_selected (selection, NULL, NULL)) {
		gtk_widget_set_sensitive (priv->edit_button, TRUE);
		gtk_widget_set_sensitive (priv->remove_button, TRUE);
	} else {
		gtk_widget_set_sensitive (priv->edit_button, FALSE);
		gtk_widget_set_sensitive (priv->remove_button, FALSE);
	}
}

static void
owners_selection_changed_cb (GtkTreeSelection *selection, gpointer user_data)
{
	SunOnePermissionsDialog *dialog = SUNONE_PERMISSIONS_DIALOG (user_data);
	SunOnePermissionsDialogPrivate *priv = dialog->priv;

	if (gtk_tree_selection_get_selected (selection, NULL, NULL))
		gtk_widget_set_sensitive (priv->owners_remove_button, TRUE);
	else
		gtk_widget_set_sensitive (priv->owners_remove_button, FALSE);
}

static void
owner_entry_insert_cb (GtkEditable *editable, gchar *new_text,
		       gint new_text_length, gint *position, gpointer data)
{
	gboolean ok = TRUE;
	int i;
	
	for (i = 0; i < new_text_length; i++) {
		char c = new_text[i];
		
		if (!((c >= 'a' && c <= 'z')
		      || (c >= 'A' && c <= 'Z')
		      || (c >= '0' && c <= '9')
		      || c == '.' || c == '_'
		      || c == '-' || c == '&'
		      || c == '!' || c == '@'))
			ok = FALSE;
	}

	if (!ok)
		g_signal_stop_emission_by_name (editable, "insert_text");
}

static void
owner_entry_changed_cb (GtkEditable *editable, gpointer user_data)
{
	const char *text;

	text = gtk_entry_get_text (GTK_ENTRY (editable));
	if (text && *text)
		 gtk_dialog_set_response_sensitive (GTK_DIALOG (user_data), GTK_RESPONSE_OK, TRUE);
	else
		 gtk_dialog_set_response_sensitive (GTK_DIALOG (user_data), GTK_RESPONSE_OK, FALSE);
}

static void
add_owner_cb (GtkButton *button, gpointer user_data)
{
	SunOnePermissionsDialog *dialog = SUNONE_PERMISSIONS_DIALOG (user_data);
	SunOnePermissionsDialogPrivate *priv = dialog->priv;
	GladeXML *xml;
	GtkWidget *id, *vbox, *entry;

	g_return_if_fail (IS_SUNONE_PERMISSIONS_DIALOG (dialog));

	/* load the dialog */
	xml = glade_xml_new (SUNONE_GLADEDIR "/sunone-permissions-dialog.glade", "add-owner-dialog-vbox", NULL);
	if (!xml) {
		e_notice (NULL, GTK_MESSAGE_ERROR, _("Could not load UI for add-owner-dialog"));
		
		return;
	}
	id = gtk_dialog_new_with_buttons ("Add owner", GTK_WINDOW(dialog), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);

	vbox = glade_xml_get_widget (xml, "add-owner-dialog-vbox");
	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (id)->vbox), vbox, TRUE, TRUE, 4);

	entry = glade_xml_get_widget (xml, "new-owner-entry");
	g_signal_connect (G_OBJECT (entry), "insert_text", G_CALLBACK (owner_entry_insert_cb), dialog);
	g_signal_connect_after (G_OBJECT (entry), "changed", G_CALLBACK (owner_entry_changed_cb), id);

	gtk_dialog_set_response_sensitive (GTK_DIALOG (id), GTK_RESPONSE_OK, FALSE);

	/* run the dialog */
	 if (gtk_dialog_run (GTK_DIALOG (id)) == GTK_RESPONSE_OK) {

		const char *user;
		user = gtk_entry_get_text (GTK_ENTRY (entry));
		if (user && *user) {
			GtkTreeIter iter;
			GtkTreeModel *model = gtk_tree_view_get_model (priv->owners_tree);
			priv->calprops->owners = g_list_append (priv->calprops->owners, g_strdup (user));
			gtk_list_store_append(GTK_LIST_STORE (model), &iter);
			gtk_list_store_set (GTK_LIST_STORE(model), &iter, 
					   OWNERS_NAME_COLUMN, 
					   user,
					   -1);

			gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
		}
	}

	gtk_widget_destroy (id);
	g_object_unref (G_OBJECT (xml));
}

static void
remove_owner_cb (GtkButton *button, gpointer user_data)
{
	SunOnePermissionsDialog *dialog = SUNONE_PERMISSIONS_DIALOG (user_data);
	SunOnePermissionsDialogPrivate *priv = dialog->priv;
	int row;
	GList *l;
	char *user;
	GtkTreeSelection * selection;
	GtkTreeModel *model;
	GtkTreePath *path;
	GtkTreeIter iter;

	g_return_if_fail (IS_SUNONE_PERMISSIONS_DIALOG (dialog));

	selection = gtk_tree_view_get_selection (priv->owners_tree);
	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
		return;

	path = gtk_tree_model_get_path (model, &iter);
	row = gtk_tree_path_get_indices (path)[0];
	gtk_tree_path_free (path);
	g_return_if_fail (row >= 0 && row < g_list_length (priv->calprops->owners));

	l = g_list_nth (priv->calprops->owners, row);
	if (!l)
		return;

	gtk_list_store_remove ((GtkListStore *) model, &iter);

	/* remove the user from the owners list */
	user = l->data;
	priv->calprops->owners = g_list_remove (priv->calprops->owners, user);
	g_free (user);

	gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
}

static void
sunone_permissions_dialog_init (SunOnePermissionsDialog *object)
{
	SunOnePermissionsDialog *dialog = SUNONE_PERMISSIONS_DIALOG (object);
	SunOnePermissionsDialogPrivate *priv;
	GtkWidget *label, *notebook;
	GtkTreeSelection *perm_selection, *owner_selection;

	dialog->priv = g_new0(SunOnePermissionsDialogPrivate, 1);
	priv = dialog->priv;

	dialog->merged_acls = NULL;
	priv->cnc = NULL;
	priv->calid = NULL;
	priv->calprops = NULL;

	/* set up the dialog */
	g_object_set (G_OBJECT (dialog), "allow_grow", TRUE, NULL);
	
	/* load UI */
	priv->xml = glade_xml_new (SUNONE_GLADEDIR "/sunone-permissions-dialog.glade",
				     "main-notebook", NULL);
	if (!priv->xml) {
		label = gtk_label_new (_("Could not load permissions dialog UI"));
		gtk_widget_show (label);
		gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), label, TRUE, TRUE, 0);
		return;
	}
	
	notebook = glade_xml_get_widget (priv->xml, "main-notebook");
	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), notebook, TRUE, TRUE, 0);

	/* permissions tab's widgets */
	priv->main_table = glade_xml_get_widget (priv->xml, "permissions-main-table");

	priv->add_button = glade_xml_get_widget (priv->xml, "permissions-add-button");
	g_signal_connect (G_OBJECT (priv->add_button), "clicked",
			    G_CALLBACK (add_permission_cb), dialog);
	priv->edit_button = glade_xml_get_widget (priv->xml, "permissions-edit-button");
	g_signal_connect (G_OBJECT (priv->edit_button), "clicked",
			    G_CALLBACK (edit_permission_cb), dialog);
	priv->remove_button = glade_xml_get_widget (priv->xml, "permissions-remove-button");
	g_signal_connect (G_OBJECT (priv->remove_button), "clicked",
			    G_CALLBACK (remove_permission_cb), dialog);

	priv->perm_tree = (GtkTreeView *)glade_xml_get_widget (priv->xml, "perm-tree");
	perm_selection = gtk_tree_view_get_selection (priv->perm_tree);
	g_signal_connect (G_OBJECT (perm_selection), "changed",
			    G_CALLBACK (permission_selection_changed_cb), dialog);

	/* owners tab's widgets */
	priv->owners_tree = (GtkTreeView *)glade_xml_get_widget (priv->xml, "owners-tree");
	owner_selection = gtk_tree_view_get_selection (priv->owners_tree);
	g_signal_connect (G_OBJECT (owner_selection), "changed",
			    G_CALLBACK (owners_selection_changed_cb), dialog);

	priv->owners_add_button = glade_xml_get_widget (priv->xml, "owners-add-button");
	g_signal_connect (G_OBJECT (priv->owners_add_button), "clicked",
			    G_CALLBACK (add_owner_cb), dialog);

	priv->owners_remove_button = glade_xml_get_widget (priv->xml, "owners-remove-button");
	g_signal_connect (G_OBJECT (priv->owners_remove_button), "clicked",
			    G_CALLBACK (remove_owner_cb), dialog);
}

static void
sunone_permissions_dialog_dispose (GObject *object)
{
	SunOnePermissionsDialog *dialog = SUNONE_PERMISSIONS_DIALOG (object);
	SunOnePermissionsDialogPrivate *priv = dialog->priv;

	g_return_if_fail (IS_SUNONE_PERMISSIONS_DIALOG (dialog));

	if (priv) {
		if (priv->calid) {
			g_free (priv->calid);
			priv->calid = NULL;
		}
		if (priv->xml) {
			g_object_unref (G_OBJECT (priv->xml));
			priv->xml = NULL;
		}
		if (priv->calprops) {
			sunone_connection_free_calprops (priv->calprops);
			priv->calprops = NULL;
		}
		if (dialog->merged_acls) {
			g_list_foreach (dialog->merged_acls, (GFunc) g_object_unref, NULL);
			g_list_free (dialog->merged_acls);
			dialog->merged_acls = NULL;
		}

		g_free (priv);
		dialog->priv = NULL;
	}

	G_OBJECT_CLASS (parent_class)->dispose (object);
}

static void
sunone_permissions_dialog_finalize (GObject *object)
{
	G_OBJECT_CLASS (parent_class) -> finalize (object);
}


G_DEFINE_TYPE (SunOnePermissionsDialog, sunone_permissions_dialog, GTK_TYPE_DIALOG)

static void
merge_acls (SunOnePermissionsDialog *dialog)
{
	SunOnePermissionsDialogPrivate *priv = dialog->priv;
	GList *l, *ll;

	for (l = priv->calprops->acls; l != NULL; l = l->next) {
		SunOneACE *real_ace, *merged_ace;

		real_ace = SUNONE_ACE (l->data);
		if ((sunone_ace_get_user_type (real_ace) != SUNONE_ACE_USERTYPE_USER 
		     && sunone_ace_get_user_type (real_ace) != SUNONE_ACE_USERTYPE_ALL_USERS)
		    || sunone_ace_get_context (real_ace) == SUNONE_ACE_CONTEXT_CALENDAR_PROPERTIES)
			continue;
		
		for (ll = dialog->merged_acls; ll != NULL; ll = ll->next) {
			merged_ace = SUNONE_ACE (ll->data);

			if (sunone_ace_get_user_type (real_ace) == sunone_ace_get_user_type (merged_ace)) {
				if (sunone_ace_get_user_type (real_ace) == SUNONE_ACE_USERTYPE_USER)
					if (strcasecmp (sunone_ace_get_user_name (real_ace), sunone_ace_get_user_name (merged_ace)))
						continue;

				/* merge it */
				if (sunone_ace_get_access_type (real_ace) == sunone_ace_get_access_type (merged_ace)) {
					sunone_ace_set_permissions (
						merged_ace,
						sunone_ace_get_permissions (merged_ace) | sunone_ace_get_permissions (real_ace));
				} else
					sunone_ace_set_permissions (
						merged_ace,
						sunone_ace_get_permissions (merged_ace) ^ sunone_ace_get_permissions (real_ace));
				break;
			}
		}

		if (!ll) {
			merged_ace = sunone_ace_clone (real_ace);
			dialog->merged_acls = g_list_append (dialog->merged_acls, merged_ace);
		}
	}
}

static void
unmerge_acls (SunOnePermissionsDialog *dialog)
{
	SunOnePermissionsDialogPrivate *priv = dialog->priv;
	GList *l, *new_acls = NULL, *rp_acls = NULL;
	
	/* Add the owner acls */
	for (l = priv->calprops->acls; l != NULL; l = l->next) {
		SunOneACE *ace = l->data;

		if (sunone_ace_get_user_type (ace) == SUNONE_ACE_USERTYPE_OWNERS)
			new_acls = g_list_append (new_acls, sunone_ace_clone (ace));
	}
	
	/* Add the user changeable acls */
	for (l = dialog->merged_acls; l != NULL; l = l->next) {
		SunOneACE *new_ace, *ace = l->data;
		SunOneACEPermission perms;
		
		/* Availability, schedule, read */
		perms = sunone_ace_get_permissions (ace);
		perms &= (SUNONE_ACE_PERMISSION_FREEBUSY | SUNONE_ACE_PERMISSION_SCHEDULE | SUNONE_ACE_PERMISSION_READ);
		new_ace = sunone_ace_new ();
		sunone_ace_set_access_type (new_ace, SUNONE_ACE_ACCESSTYPE_GRANT);
		sunone_ace_set_user_type (new_ace, sunone_ace_get_user_type (ace));
		sunone_ace_set_user_name (new_ace, sunone_ace_get_user_name (ace));
		sunone_ace_set_context (new_ace, SUNONE_ACE_CONTEXT_ENTIRE_CALENDAR);
		sunone_ace_set_permissions (new_ace, perms);
		new_acls = g_list_append (new_acls, new_ace);
		
		/* Delete, modify */
		perms = sunone_ace_get_permissions (ace);
		perms &= (SUNONE_ACE_PERMISSION_DELETE | SUNONE_ACE_PERMISSION_WRITE);
		new_ace = sunone_ace_new ();
		sunone_ace_set_access_type (new_ace, SUNONE_ACE_ACCESSTYPE_GRANT);
		sunone_ace_set_user_type (new_ace, sunone_ace_get_user_type (ace));
		sunone_ace_set_user_name (new_ace, sunone_ace_get_user_name (ace));
		sunone_ace_set_context (new_ace, SUNONE_ACE_CONTEXT_CALENDAR_COMPONENTS);
		sunone_ace_set_permissions (new_ace, perms);
		new_acls = g_list_append (new_acls, new_ace);
		
		/* The read properties ability (if any other perms are set */
		if (sunone_ace_get_permissions (ace) != SUNONE_ACE_PERMISSION_NONE) {
			new_ace = sunone_ace_new ();
			sunone_ace_set_access_type (new_ace, SUNONE_ACE_ACCESSTYPE_GRANT);
			sunone_ace_set_user_type (new_ace, sunone_ace_get_user_type (ace));
			sunone_ace_set_user_name (new_ace, sunone_ace_get_user_name (ace));
			sunone_ace_set_context (new_ace, SUNONE_ACE_CONTEXT_CALENDAR_PROPERTIES);
			sunone_ace_set_permissions (new_ace, SUNONE_ACE_PERMISSION_READ);
			rp_acls = g_list_append (rp_acls, new_ace);
		}
	}

	g_list_foreach (priv->calprops->acls, (GFunc) g_object_unref, NULL);
	g_list_free (priv->calprops->acls);
	priv->calprops->acls = g_list_concat (new_acls, rp_acls);
}

static void
dialog_button_clicked_cb (GtkWidget *gdialog, gint response, gpointer user_data)
{
	SunOnePermissionsDialog *dialog = SUNONE_PERMISSIONS_DIALOG (gdialog);
	SunOnePermissionsDialogPrivate *priv = dialog->priv;
	guint rc;

	g_return_if_fail (IS_SUNONE_PERMISSIONS_DIALOG (dialog));

	if (response == GTK_RESPONSE_OK) {
		unmerge_acls (dialog);
		rc = sunone_connection_set_calprops (priv->cnc, priv->calid, priv->calprops);

		if (!SUNONE_ERROR_IS_SUCCESSFUL (rc)) {
			e_notice (GTK_WINDOW (dialog),  GTK_MESSAGE_ERROR,_("Could not set permissions for the folder"));  
			return;
			
		}
	}

	gtk_widget_destroy (GTK_WIDGET (gdialog));
}


static void
init_dialog (SunOnePermissionsDialog *dialog)
{
	SunOnePermissionsDialogPrivate *priv = dialog->priv;
	GtkListStore *perm_model;
	GtkListStore *owners_model;
	GtkCellRenderer *renderer;

	/* set the permissions list */
	perm_model = gtk_list_store_new (PERM_TREE_N_COLUMNS, G_TYPE_STRING,
					G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
					G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
					G_TYPE_BOOLEAN);
	gtk_tree_view_set_model (priv->perm_tree, (GtkTreeModel *)perm_model);

	renderer = gtk_cell_renderer_text_new ();
	gtk_tree_view_insert_column_with_attributes (priv->perm_tree,
						    -1, 
						    _("Name"), renderer,
						    "text", 
						    PERM_NAME_COLUMN,
						    NULL);

	renderer = gtk_cell_renderer_toggle_new();
	gtk_tree_view_insert_column_with_attributes (priv->perm_tree, -1,
						    _("Availability"), renderer,
						    "active", 
						    PERM_AVAILABILITY_COLUMN, 
						    NULL);
	renderer = gtk_cell_renderer_toggle_new();
	gtk_tree_view_insert_column_with_attributes (priv->perm_tree, -1,
						    _("Invite"), renderer,
						    "active", 
						    PERM_INVITE_COLUMN, 
						    NULL);

	renderer = gtk_cell_renderer_toggle_new();
	gtk_tree_view_insert_column_with_attributes (priv->perm_tree, -1,
						    _("Read"), renderer,
						    "active", 
						    PERM_READ_COLUMN, 
						    NULL);
	renderer = gtk_cell_renderer_toggle_new();
	gtk_tree_view_insert_column_with_attributes (priv->perm_tree, -1,
						    _("Delete"), renderer,
						    "active", 
						    PERM_DELETE_COLUMN, 
						    NULL);
	renderer = gtk_cell_renderer_toggle_new();
	gtk_tree_view_insert_column_with_attributes (priv->perm_tree, -1,
						    _("Modify"), renderer,
						    "active", 
						    PERM_MODIFY_COLUMN, 
						    NULL);

	if (dialog->merged_acls) {
		GList *l;
	
		for (l = dialog->merged_acls; l != NULL; l = l->next) {
			SunOneACEPermission perms;
			const char *name_str;
			static char buf[1024];
			GtkTreeIter iter;

			perms = sunone_ace_get_permissions (SUNONE_ACE (l->data));
			switch (sunone_ace_get_user_type (SUNONE_ACE (l->data))) {
			case SUNONE_ACE_USERTYPE_USER :
				name_str = sunone_ace_get_user_name (SUNONE_ACE (l->data));
				break;
			case SUNONE_ACE_USERTYPE_DOMAIN :
				sprintf (buf, _("Domain %s"), sunone_ace_get_user_name (SUNONE_ACE (l->data)));
				name_str = buf;
				break;
			case SUNONE_ACE_USERTYPE_ALL_USERS :
				name_str =  _("Everybody");
				break;
			case SUNONE_ACE_USERTYPE_PRIMARY_OWNERS :
				name_str = _("Primary owners");
				break;
			case SUNONE_ACE_USERTYPE_OWNERS :
				name_str = _("Owners");
				break;
			case SUNONE_ACE_USERTYPE_NONOWNERS :
				name_str = _("Non-owners");
				break;
			default :
				name_str = "";
			}

			gtk_list_store_append (perm_model, &iter);
			gtk_list_store_set (perm_model, &iter,
				PERM_NAME_COLUMN,
				name_str,
				PERM_AVAILABILITY_COLUMN,
				perms & SUNONE_ACE_PERMISSION_FREEBUSY,
				PERM_INVITE_COLUMN,
				perms & SUNONE_ACE_PERMISSION_SCHEDULE,
				PERM_READ_COLUMN,
				perms & SUNONE_ACE_PERMISSION_READ,
				PERM_DELETE_COLUMN,
				perms & SUNONE_ACE_PERMISSION_DELETE,
				PERM_MODIFY_COLUMN,
				perms & SUNONE_ACE_PERMISSION_WRITE,
				 -1);
		}
	}
	
	/* set the owners list */
	owners_model = gtk_list_store_new (OWNERS_TREE_N_COLUMNS, G_TYPE_STRING);
	gtk_tree_view_set_model (priv->owners_tree, (GtkTreeModel *)owners_model);
	renderer = gtk_cell_renderer_text_new ();
	gtk_tree_view_insert_column_with_attributes (priv->owners_tree,
						    -1, 
						    _("User"), renderer,
						    "text", 
						    OWNERS_NAME_COLUMN,
						    NULL);

	if (priv->calprops) {
		GList *l;
		
		for (l = priv->calprops->owners; l != NULL; l = l->next) {
			GtkTreeIter iter;

			gtk_list_store_append (owners_model, &iter);
			gtk_list_store_set (owners_model, &iter, 
					   OWNERS_NAME_COLUMN,
					   (const char *) l->data,
					   -1);
		}
	}
}

GtkWidget *
sunone_permissions_dialog_new (SunOneConnection *cnc, const gchar *calid)
{
	SunOnePermissionsDialog *dialog;
	SunOnePermissionsDialogPrivate *priv;

	g_return_val_if_fail (IS_SUNONE_CONNECTION (cnc), NULL);
	g_return_val_if_fail (calid != NULL, NULL);

	dialog = g_object_new (SUNONE_PERMISSIONS_DIALOG_TYPE, NULL);
	priv = dialog->priv;
	priv->cnc = cnc;
	priv->calid = g_strdup (calid);
	gtk_window_set_title (GTK_WINDOW (dialog), _("Folder permissions"));
	gtk_widget_set_size_request(GTK_WIDGET (dialog), 500, 400);

	gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);

	gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);

	g_signal_connect (dialog, "response",
		G_CALLBACK (dialog_button_clicked_cb), NULL);

	/* get properties for this calendar */
	priv->calprops = sunone_connection_get_calprops (priv->cnc, priv->calid, FALSE);
	if (!priv->calprops) {
		gtk_widget_destroy (GTK_WIDGET (dialog));
		e_notice (NULL, GTK_MESSAGE_ERROR, _("Could not get properties for this folder."));
		return NULL;
	}

	merge_acls (dialog);
	init_dialog (dialog);

	return GTK_WIDGET (dialog);
}

GtkTreeView *
sunone_permissions_dialog_get_permissions_tree_view(SunOnePermissionsDialog *dialog)
{
	SunOnePermissionsDialogPrivate *priv = dialog->priv;

	g_return_val_if_fail (IS_SUNONE_PERMISSIONS_DIALOG (dialog), NULL);
	return priv->perm_tree;
}
