/* an example of a history side bar plugin for SkipStone
 * Maher <muhri@muhri.net> */
#include "../../src/skipstone.h"
#include "../../src/skipstone-plugin.h"

GCompletion *cmp = NULL;

#define PLUGIN_NAME "AutoComplete"

typedef struct _SkipCompleter SkipCompleter;

static gint displayAlt=1;

static void create_plugin(SkipStone *skipstone);
static GtkWidget * create_config(void);
static void save_config(GtkWidget *myWidget);
static gboolean complete(GtkWidget *entry, GdkEventKey *ev, SkipCompleter *sc);
static void create_popup(SkipCompleter *sc, GList *l);
static void die(GtkWidget *w, SkipCompleter *sc);
static void activate_item(GtkWidget *menuitem, SkipCompleter *sc);
static GList *autocomplete_get_history(void);

struct _SkipCompleter
{
   GtkWidget *complete_window;
   SkipStone *ss;
};


static SkipStonePlugin plugin =
{
	  PLUGIN_NAME, /* plugin name */
	  PLUGIN_IN_TOOLBAR, /* position left of embedding widget */
	  create_plugin,/* create plugin function */
       	  create_config,
       	  save_config,
	  1 /* do we create this plugin for each window */
};


static GList *autocomplete_get_history(void)
{
     GList *ret=NULL;
     GSList *hist = NULL, *l = NULL;
     hist = skipstone_get_history();
     for (l = hist; l; l = l->next) 
	  ret = g_list_append(ret, l->data);
     g_slist_free(hist);
     return ret;
}
	       
static void create_popup(SkipCompleter *sc, GList *l)
{
   GList *ll;     	
   gint i = 0;
   if (sc->complete_window != NULL) {
      gtk_widget_destroy(sc->complete_window);
      sc->complete_window = NULL;
   }
   
   sc->complete_window = gtk_menu_new();
   GTK_WIDGET_UNSET_FLAGS(sc->complete_window,GTK_CAN_FOCUS);
   for (ll =l; ll ; ll = ll->next)
     {
	GtkWidget *label = gtk_menu_item_new_with_label(ll->data);
	g_signal_connect(G_OBJECT(label), "activate", G_CALLBACK(activate_item), sc);
	g_object_set_data(G_OBJECT(label), "url", ll->data);
	gtk_menu_append(GTK_MENU(sc->complete_window), label);
	  i++;
	  if (i == 15) break;
     }
   
   gtk_widget_show_all(sc->complete_window);
   gtk_menu_popup(GTK_MENU(sc->complete_window), NULL,
		  NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
}

static void activate_item(GtkWidget *menuitem, SkipCompleter *sc)
{
   gchar *url;
   
   url = gtk_object_get_data(GTK_OBJECT(menuitem), "url");
   g_return_if_fail (url != NULL);
   gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(sc->ss->combo)->entry), url);
   skipstone_load_url_cb(sc->ss, url);
   gtk_widget_destroy(sc->complete_window);
   sc->complete_window=NULL;
}


static gboolean complete(GtkWidget *entry, GdkEventKey *ev, SkipCompleter *sc)
{
     if (!entry || !GTK_IS_WIDGET(entry)) {
	  return FALSE;
     }

     if (ev->keyval == GDK_Tab)
     {
	
	GList *possible = NULL;
	static gchar *new_prefix=NULL;
	G_CONST_RETURN gchar *current = gtk_entry_get_text(GTK_ENTRY(entry));
	gchar *t;
	if (!current  || current == NULL || !strcmp(current,""))
	  {
	     
	     g_warning("NULL text in gtkentry\n");
	     return FALSE;
	  }
	t = g_strdup(current);
	t = g_strstrip(t);	
	possible = g_completion_complete(cmp, t, &new_prefix);

	
/*	g_print("new perfix is %s\n",new_prefix); */
	
	if (new_prefix) gtk_entry_set_text(GTK_ENTRY(entry), new_prefix);
	
	if (((ev->state & GDK_CONTROL_MASK) || displayAlt) && possible && g_list_length(possible) > 1)
	  {
	     create_popup(sc,possible);
	  }
	
	  g_free(t);
/*	FIXME: 
 *      possible = NULL;
 *	if (new_prefix) g_free(new_prefix); 
 */
	if (entry && GTK_IS_WIDGET(entry))
	    g_signal_stop_emission_by_name (G_OBJECT(entry), "key_press_event");
	  return TRUE;
     } else if (ev->keyval == 65293 || ev->keyval == 65421)
	  {
	     
	     if (sc->complete_window != NULL)
	       {		  	       		  
		  gtk_widget_destroy(sc->complete_window);
		  sc->complete_window = NULL;
	       }
	     return FALSE;
	  }

   return FALSE;
   
}

static void save_config(GtkWidget *myWidget)
{
   GtkWidget *altCheck=NULL;
   g_return_if_fail(myWidget != NULL);
   altCheck = gtk_object_get_data(GTK_OBJECT(myWidget), "altCheck");
   g_return_if_fail(altCheck != NULL);
   displayAlt = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(altCheck));
   skipstone_set_config_value_as_int(PLUGIN_NAME, "displayAlt", displayAlt);

   return;
}

static GtkWidget *create_config(void)
{
   GtkWidget *ret = NULL;
   GtkWidget *altCheck=NULL;
   GtkWidget *label=NULL;
   ret = gtk_vbox_new(FALSE, 5);
   altCheck = gtk_check_button_new_with_label("Display Alternative autocompletion items when there is more than 1 match?");
   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(altCheck), displayAlt);
   gtk_box_pack_start(GTK_BOX(ret), altCheck, FALSE, FALSE, 0);
   label = gtk_label_new("Hitting Tab and Control together when Display Alternative Autocompletion\nis off overrides this option and displays the alternatives.");
   gtk_box_pack_start(GTK_BOX(ret), label, FALSE, FALSE, 0);
   gtk_object_set_data(GTK_OBJECT(ret), "altCheck", altCheck);
   gtk_widget_show_all(ret);
   return ret;
}

static void create_plugin(SkipStone *skipstone)
{
   SkipCompleter *sc = NULL;
   sc = g_new0(SkipCompleter,1);
   sc->complete_window = NULL;
   sc->ss = skipstone;
   gtk_signal_connect_while_alive(GTK_OBJECT(GTK_COMBO(skipstone->combo)->entry),
				  "key_press_event", 
		      GTK_SIGNAL_FUNC(complete), sc, GTK_OBJECT(GTK_COMBO(skipstone->combo)->entry));
				  
   g_signal_connect(G_OBJECT(GTK_COMBO(skipstone->combo)->entry), 
			    "unrealize",
			    G_CALLBACK(die), sc);
}


static void die (GtkWidget *w, SkipCompleter *sc) 
{

     gtk_signal_disconnect_by_func(GTK_OBJECT(w),
	                       GTK_SIGNAL_FUNC(complete),
			       sc);
     g_free(sc);
     sc = NULL;

}


SkipStonePlugin *init_plugin(void)
{
   if (cmp == NULL) 
     cmp = g_completion_new(NULL);
     g_completion_add_items(cmp,autocomplete_get_history());

   if ((displayAlt = skipstone_get_config_value_as_int(PLUGIN_NAME, "displayAlt")) == -1) 
     {

	displayAlt=1;
	skipstone_set_config_value_as_int(PLUGIN_NAME, "displayAlt", displayAlt);
     }
   
   return &plugin;
}
