/* properties.c -- properties dialog box and session management for character
 * picker applet. Much of this is adapted from modemlights/properties.c
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "charpick.h"

#include <string.h>

#include <atk/atkrelation.h>
#include <gtk/gtk.h>

#define CHARPICK_STOCK_EDIT "charpick-stock-edit"

#if GTK_CHECK_VERSION (3, 0, 0)
#define gtk_vbox_new(X,Y) gtk_box_new(GTK_ORIENTATION_VERTICAL,Y)
#define gtk_hbox_new(X,Y) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,Y)
#endif

void
register_stock_for_edit (void)
{
  static gboolean registered = FALSE;
  if (!registered)
  {
    GtkIconFactory *factory;
    GtkIconSet     *icons;

    static const GtkStockItem edit_item [] = {
           { CHARPICK_STOCK_EDIT, N_("_Edit"), 0, 0, GETTEXT_PACKAGE },
    };
    icons = gtk_icon_factory_lookup_default (GTK_STOCK_PREFERENCES);
    factory = gtk_icon_factory_new ();
    gtk_icon_factory_add (factory, CHARPICK_STOCK_EDIT, icons);
    gtk_icon_factory_add_default (factory);
    gtk_stock_add_static (edit_item, 1);
    registered = TRUE;
  }
}

#if 0
static void
set_atk_relation (GtkWidget *label, GtkWidget *widget)
{
  AtkObject *atk_widget;
  AtkObject *atk_label;
  AtkRelationSet *relation_set;
  AtkRelation *relation;
  AtkObject *targets[1];

  atk_widget = gtk_widget_get_accessible (widget);
  atk_label = gtk_widget_get_accessible (label);
  
  /* set label-for relation */
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);	

  /* return if gail is not loaded */
  if (GTK_IS_ACCESSIBLE (atk_widget) == FALSE)
    return;

  /* set label-by relation */
  relation_set = atk_object_ref_relation_set (atk_widget);
  targets[0] = atk_label;
  relation = atk_relation_new (targets, 1, ATK_RELATION_LABELLED_BY);
  atk_relation_set_add (relation_set, relation);
  g_object_unref (G_OBJECT (relation)); 
}
#endif /* 0 */

/* sets accessible name and description */

static void
set_access_namedesc (GtkWidget *widget, const gchar *name, const gchar *desc)
{
    AtkObject *obj;

    obj = gtk_widget_get_accessible (widget);
    if (! GTK_IS_ACCESSIBLE (obj))
       return;

    if ( desc )
       atk_object_set_description (obj, desc);
    if ( name )
       atk_object_set_name (obj, name);
}

void
add_edit_dialog_create (charpick_data *curr_data, gchar *string, gchar *title)
{
	GtkWidget *dialog;
	GtkWidget *entry;
	GtkWidget *dbox;
	GtkWidget *vbox, *hbox;
	GtkWidget *label;

	dialog = gtk_dialog_new_with_buttons (_(title), GTK_WINDOW (curr_data->propwindow),
							    GTK_DIALOG_DESTROY_WITH_PARENT,
							    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
							    GTK_STOCK_OK, GTK_RESPONSE_OK,
							    NULL);

	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (curr_data->propwindow));
	gtk_widget_set_sensitive (curr_data->propwindow, FALSE);

	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area(GTK_DIALOG (dialog))), 2);

	dbox = gtk_dialog_get_content_area(GTK_DIALOG (dialog));
	
	vbox = gtk_vbox_new (FALSE, 12);
	gtk_box_pack_start (GTK_BOX (dbox), vbox, TRUE, TRUE, 0);
	gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
	
	hbox = gtk_hbox_new (FALSE, 12);
	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
	
	label = gtk_label_new_with_mnemonic (_("_Palette:"));
	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
		
	entry = gtk_entry_new ();
	gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
	 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
	gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);

	set_access_namedesc (entry, _("Palette entry"),
				         _("Modify a palette by adding or removing characters"));
	if (string)
		gtk_entry_set_text (GTK_ENTRY (entry), string);

	curr_data->add_edit_dialog = dialog;
	curr_data->add_edit_entry = entry;
}

static void
add_palette_cb (GtkDialog *dialog, int response_id, charpick_data *curr_data)
{
	GList *list = curr_data->chartable;
	GtkTreeModel *model;
	GtkTreeIter iter;
	GtkTreeSelection *selection;
	GtkTreePath *path;
	char *new;

	gtk_widget_set_sensitive (curr_data->propwindow, TRUE);

	if (response_id != GTK_RESPONSE_OK) {
		gtk_widget_destroy (curr_data->add_edit_dialog);
		return;
	}
	
	new = gtk_editable_get_chars (GTK_EDITABLE (curr_data->add_edit_entry), 0, -1);

	gtk_widget_destroy (curr_data->add_edit_dialog);

	if (!new || strlen (new) == 0)
		return;
	
	list = g_list_append (list, new);

	if (curr_data->chartable == NULL) {
		curr_data->chartable = list;
		curr_data->charlist = curr_data->chartable->data;
		build_table (curr_data);

		if (g_settings_is_writable (curr_data->settings, "current-list"))
			g_settings_set_string (curr_data->settings,
						      "current-list", 
					  	       curr_data->charlist);
	}

	save_chartable (curr_data);
  	populate_menu (curr_data);
  	
  	model = gtk_tree_view_get_model (GTK_TREE_VIEW (curr_data->pref_tree));

	gtk_list_store_append (GTK_LIST_STORE (model), &iter);
	gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, new, 1, new, -1);

	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (curr_data->pref_tree));
	gtk_tree_selection_select_iter (selection, &iter);

	path = gtk_tree_model_get_path (model, &iter);
	gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (curr_data->pref_tree), path,
						  NULL, FALSE, 0.0, 0.0);

	gtk_tree_path_free (path);
}

static void
edit_palette_cb (GtkDialog *dialog, int response_id, charpick_data *curr_data)
{
	GtkTreeSelection *selection;
	GtkTreeIter iter;
	GtkTreeModel *model;
	GList *list;
	char *new, *charlist;

	gtk_widget_set_sensitive (curr_data->propwindow, TRUE);

        if (response_id != GTK_RESPONSE_OK) {
		gtk_widget_destroy (curr_data->add_edit_dialog);
		return;
	}

	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (curr_data->pref_tree));

	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
		return;

	gtk_tree_model_get (model, &iter, 1, &charlist, -1);

	new = gtk_editable_get_chars (GTK_EDITABLE (curr_data->add_edit_entry), 0, -1);

	gtk_widget_destroy (curr_data->add_edit_dialog);
	
	if (!new || (g_ascii_strcasecmp (new, charlist) == 0))
		return;
		
	list = g_list_find (curr_data->chartable, charlist);
	list->data = new;
	save_chartable (curr_data);
  	populate_menu (curr_data);
	gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, new, 1, new, -1);
	
	if (g_ascii_strcasecmp (curr_data->charlist, charlist) == 0) {
		curr_data->charlist = new;
		build_table (curr_data);

		if (g_settings_is_writable (curr_data->settings, "current-list"))
			g_settings_set_string (curr_data->settings, "current-list", curr_data->charlist);
	}
	
	g_free (charlist);
}

static void
add_palette (GtkButton *buttonk, charpick_data *curr_data)
{
	if (curr_data->add_edit_dialog == NULL) {
		add_edit_dialog_create (curr_data, NULL, _("Add Palette"));

		g_signal_connect (curr_data->add_edit_dialog, 
				  "response", 
				  G_CALLBACK (add_palette_cb),
				  curr_data);

		g_signal_connect (curr_data->add_edit_dialog,
				  "destroy",
				  G_CALLBACK (gtk_widget_destroyed),
				  &curr_data->add_edit_dialog);

		gtk_widget_show_all (curr_data->add_edit_dialog);
	} else {
		gtk_window_set_screen (GTK_WINDOW (curr_data->add_edit_dialog),
				       gtk_widget_get_screen (GTK_WIDGET (curr_data->applet)));

		gtk_window_present (GTK_WINDOW (curr_data->add_edit_dialog));
	}
}

static void
edit_palette (GtkButton *button, charpick_data *curr_data)
{
	GtkTreeSelection *selection;
	GtkTreeIter iter;
	GtkTreeModel *model;
	char *charlist;

	if (curr_data->add_edit_dialog == NULL) {
		selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (curr_data->pref_tree));

		if (!gtk_tree_selection_get_selected (selection, &model, &iter))
			return;

		gtk_tree_model_get (model, &iter, 1, &charlist, -1);
		
		add_edit_dialog_create (curr_data, charlist, _("Edit Palette"));

		g_signal_connect (curr_data->add_edit_dialog, 
				  "response", 
				  G_CALLBACK (edit_palette_cb),
				  curr_data);

		g_signal_connect (curr_data->add_edit_dialog,
				  "destroy",
				  G_CALLBACK (gtk_widget_destroyed),
				  &curr_data->add_edit_dialog);

		gtk_widget_show_all (curr_data->add_edit_dialog);
	} else {
		gtk_window_set_screen (GTK_WINDOW (curr_data->add_edit_dialog),
				       gtk_widget_get_screen (GTK_WIDGET (curr_data->applet)));

		gtk_window_present (GTK_WINDOW (curr_data->add_edit_dialog));
	}
}

static void
delete_palette (GtkButton *button, charpick_data *curr_data)
{
	GtkTreeSelection *selection;
	GtkTreeIter iter, next;
	GtkTreeModel *model;
	gchar *charlist;
	
	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (curr_data->pref_tree));
	
	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
		return;
		
	gtk_tree_model_get (model, &iter, 1, &charlist, -1);
	
	curr_data->chartable = g_list_remove (curr_data->chartable, charlist);
	
	if (g_ascii_strcasecmp (curr_data->charlist, charlist) == 0) {
		curr_data->charlist = curr_data->chartable != NULL ? 
				      curr_data->chartable->data : "";
		if (g_settings_is_writable (curr_data->settings, "current-list"))
			g_settings_set_string (curr_data->settings, "current-list", curr_data->charlist);
	}
	g_free (charlist);
	
	save_chartable (curr_data);
  	populate_menu (curr_data);
  	
  	gtk_widget_grab_focus (curr_data->pref_tree);
  	next = iter;
	if (gtk_tree_model_iter_next (model, &next) )
		gtk_tree_selection_select_iter (selection, &next);
	else {
		GtkTreePath *path;
		path = gtk_tree_model_get_path (model, &iter);
		if (gtk_tree_path_prev (path))
			gtk_tree_selection_select_path (selection, path);
		gtk_tree_path_free (path);
	}
	gtk_list_store_remove (GTK_LIST_STORE (model), &iter);

}

static void
selection_changed (GtkTreeSelection *selection, gpointer data)
{
	GtkWidget *scrolled = data;
	GtkWidget *edit_button, *delete_button;
	gboolean selected;
	
	selected = gtk_tree_selection_get_selected (selection, NULL, NULL);
	edit_button = g_object_get_data (G_OBJECT (scrolled), "edit_button");
	gtk_widget_set_sensitive (edit_button, selected);
	delete_button = g_object_get_data (G_OBJECT (scrolled), "delete_button");
	gtk_widget_set_sensitive (delete_button, selected);
}

static GtkWidget *
create_palettes_tree (charpick_data *curr_data, GtkWidget *label)
{
	GtkWidget *scrolled;
	GtkWidget *tree;
	GtkListStore *model;
	GtkCellRenderer *cell;
	GtkTreeViewColumn *column;
	GList *list = curr_data->chartable;
	GtkTreeSelection *selection;
	
	scrolled = gtk_scrolled_window_new (NULL,NULL);
	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
						GTK_POLICY_AUTOMATIC,
						GTK_POLICY_AUTOMATIC);
	
	model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
	tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
	curr_data->pref_tree = tree;
	gtk_label_set_mnemonic_widget (GTK_LABEL (label), tree);
	gtk_container_add (GTK_CONTAINER (scrolled), tree);
	set_access_namedesc (tree, 
				         _("Palettes list"),
				         _("List of available palettes"));
	g_object_unref (G_OBJECT (model));
	cell = gtk_cell_renderer_text_new ();
  	column = gtk_tree_view_column_new_with_attributes ("hello",
						    	   cell,
						     	   "text", 0,
						     	   NULL);
	gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree), FALSE);
        
        while (list) {
        	GtkTreeIter iter;
        	gchar *charlist = list->data;
        	
        	gtk_list_store_append (GTK_LIST_STORE (model), &iter);
		gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, charlist, 1, charlist, -1);
        
        	list = g_list_next (list);
        }
        
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
        g_signal_connect (G_OBJECT (selection), "changed",
        			   G_CALLBACK (selection_changed), scrolled);

	return scrolled;

}

static GtkWidget *
create_hig_catagory (GtkWidget *main_box, gchar *title)
{
	GtkWidget *vbox, *vbox2, *hbox;
	GtkWidget *label;
	gchar *tmp;
		
	vbox = gtk_vbox_new (FALSE, 6);
	gtk_box_pack_start (GTK_BOX (main_box), vbox, TRUE, TRUE, 0);

	tmp = g_strdup_printf ("<b>%s</b>", title);
	label = gtk_label_new (NULL);
	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
	gtk_label_set_markup (GTK_LABEL (label), tmp);
	g_free (tmp);
	gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

	hbox = gtk_hbox_new (FALSE, 0);
	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
	
	label = gtk_label_new ("    ");
	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
	
	vbox2 = gtk_vbox_new (FALSE, 6);
	gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);

	return vbox2;
		
}

static void default_chars_frame_create(charpick_data *curr_data)
{
  GtkWidget *dialog = curr_data->propwindow;
  GtkWidget *dbox, *vbox, *vbox1, *vbox2, *vbox3;
  GtkWidget *hbox;
  GtkWidget *label;
  GtkWidget *scrolled;
  GtkWidget *button;

  dbox = gtk_dialog_get_content_area(GTK_DIALOG (dialog));

  vbox = gtk_vbox_new (FALSE, 18);
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
  gtk_box_pack_start (GTK_BOX (dbox), vbox, TRUE, TRUE, 0);

  vbox1 = create_hig_catagory (vbox, _("Character Palette")); 
  
  vbox3 = gtk_vbox_new (FALSE, 6);
  gtk_box_pack_start (GTK_BOX (vbox1), vbox3, TRUE, TRUE, 0);
  
  label = gtk_label_new_with_mnemonic(_("_Palettes:"));
  gtk_box_pack_start(GTK_BOX(vbox3), label, FALSE, FALSE, 0);
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_widget_show(label);
	  
  hbox = gtk_hbox_new (FALSE, 12);
  gtk_box_pack_start (GTK_BOX (vbox3), hbox, TRUE, TRUE, 0); 
  scrolled = create_palettes_tree (curr_data, label);
  gtk_box_pack_start (GTK_BOX (hbox), scrolled, TRUE, TRUE, 0);
  
  vbox2 = gtk_vbox_new (FALSE, 6);
  gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
  button = gtk_button_new_from_stock (GTK_STOCK_ADD);
  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
  g_signal_connect (G_OBJECT (button), "clicked",
  			     G_CALLBACK (add_palette), curr_data);
  set_access_namedesc (button, _("Add button"),
				         _("Click to add a new palette"));
 
  button = gtk_button_new_from_stock (CHARPICK_STOCK_EDIT);
  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
  g_signal_connect (G_OBJECT (button), "clicked",
  			     G_CALLBACK (edit_palette), curr_data);
  g_object_set_data (G_OBJECT (scrolled), "edit_button", button);
  set_access_namedesc (button, _("Edit button"),
				         _("Click to edit the selected palette"));
  
  button = gtk_button_new_from_stock (GTK_STOCK_DELETE);
  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
  g_signal_connect (G_OBJECT (button), "clicked",
  			     G_CALLBACK (delete_palette), curr_data);
  g_object_set_data (G_OBJECT (scrolled), "delete_button", button);
  set_access_namedesc (button, _("Delete button"),
				         _("Click to delete the selected palette"));

  if ( ! g_settings_is_writable (curr_data->settings, "chartable"))
	  gtk_widget_set_sensitive (vbox3, FALSE);
   
  return;
}

static void
phelp_cb (GtkDialog *dialog, gint tab, gpointer data)
{
  GError *error = NULL;

  gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (dialog)),
                "help:mate-char-palette/charpick-prefs",
                gtk_get_current_event_time (),
                &error);

  if (error) { /* FIXME: the user needs to see this */
    g_warning ("help error: %s\n", error->message);
    g_error_free (error);
    error = NULL;
  }
}

static void
response_cb (GtkDialog *dialog, gint id, gpointer data)
{
  charpick_data *curr_data = data;

  if(id == GTK_RESPONSE_HELP){
    phelp_cb (dialog,id,data);
    return;
  }
  
  gtk_widget_destroy (curr_data->propwindow);
  curr_data->propwindow = NULL;
  
}

void
show_preferences_dialog (GtkAction     *action,
			 charpick_data *curr_data)
{
  if (curr_data->propwindow) {
    gtk_window_set_screen (GTK_WINDOW (curr_data->propwindow),
			   gtk_widget_get_screen (curr_data->applet));
    gtk_window_present (GTK_WINDOW (curr_data->propwindow));
    return;
  }

  curr_data->propwindow = gtk_dialog_new_with_buttons (_("Character Palette Preferences"), 
  					    NULL,
					    GTK_DIALOG_DESTROY_WITH_PARENT,
					    GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
					    GTK_STOCK_HELP, GTK_RESPONSE_HELP,
					    NULL);
  gtk_window_set_screen (GTK_WINDOW (curr_data->propwindow),
			 gtk_widget_get_screen (curr_data->applet));
  gtk_window_set_default_size (GTK_WINDOW (curr_data->propwindow), 350, 350);
  gtk_container_set_border_width (GTK_CONTAINER (curr_data->propwindow), 5);
  gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area(GTK_DIALOG (curr_data->propwindow))), 2);
  gtk_dialog_set_default_response (GTK_DIALOG (curr_data->propwindow), GTK_RESPONSE_CLOSE);

  default_chars_frame_create(curr_data);
  g_signal_connect (G_OBJECT (curr_data->propwindow), "response",
  		    G_CALLBACK (response_cb), curr_data);
  		    
  gtk_widget_show_all (curr_data->propwindow);
}