#include "../../src/skipstone.h"
#include <gdk/gdkx.h>
#include <Imlib2.h>

#define THROB_BASE_DIR "/.skipstone/plugins/throbbers"
#define DEFAULT_THROB  "pacspin"

static void create_plugin(SkipStone *ss);
static GtkWidget *create_config(void);
static void save_my_config(GtkWidget *my_widget);
static void load_images(void);
static void set_throbdir(void);
static void free_images(void);

typedef struct
{
     gint timer;
     gint pos;
     gint spining;
     GtkWidget *da;
     SkipStone *ss;
     GtkWidget *button;
}Throbber;

static Imlib_Image im[35];
static gchar *home_page=NULL,*throbdir=NULL;
static gint num_files = 0;
static GList *tdir_list=NULL;
static GSList *throbber_list=NULL;

static SkipStonePlugin plugin =
{
     "Throb",
       PLUGIN_IN_TOOLBAR,
       create_plugin,
       create_config,
       save_my_config,
       1
};

static gint timeout(Throbber *th);
static void on_throbber_destroy(GtkWidget *da, Throbber *th);
static void spin(Throbber *th);
static void stop(Throbber *th);
static void on_expose(GtkWidget *da, GdkEvent *ev, Throbber *th);
static void init_imlib_and_load_files(GtkWidget *da, GdkEvent *ev, Throbber *th);
static void on_throbber_click(GtkWidget *b, Throbber *th);
static void set_tdir_list();
static gboolean is_tdir_present( gchar *value );

static void on_expose(GtkWidget *da, GdkEvent *ev, Throbber *th) 
{
     	imlib_context_set_drawable(GDK_WINDOW_XWINDOW((th->da)->window));
     	imlib_context_set_image(im[0]);
     	gdk_window_clear(da->window);
     	imlib_render_image_on_drawable_at_size(0,0,24,24);
}

static void save_my_config(GtkWidget *my_widget)
{
	GtkWidget *homepage, *interval;
	GtkWidget *throbCombo;
	GSList *l=NULL;
	gchar *entry, *current_entry;


     	g_return_if_fail ( my_widget != NULL);
     	homepage = gtk_object_get_data(GTK_OBJECT(my_widget), "homepage");
     	interval = gtk_object_get_data(GTK_OBJECT(my_widget), "interval");

     	throbCombo = gtk_object_get_data(GTK_OBJECT(my_widget), "throb_combo");

     	skipstone_set_config_value_as_int("Throbber","Interval",
					  atoi(gtk_entry_get_text(GTK_ENTRY(interval))));
     	skipstone_set_config_value_as_str("Throbber","HomePage",
					  gtk_entry_get_text(GTK_ENTRY(homepage)));

     	current_entry = skipstone_get_config_value_as_str("Throbber","ThrobDir");
     	entry = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(throbCombo)->entry) );

     	if ( !is_tdir_present( entry ) || 
	    !strcmp( current_entry, entry ) )  return; 

     	skipstone_set_config_value_as_str("Throbber","ThrobDir", entry );
					  

        set_throbdir();
     	free_images();
     	load_images();
	
     	for (l=throbber_list;l;l=l->next){
	     	Throbber *th = (Throbber *)l->data;
	     	if (!th || th==NULL) continue;
	     	imlib_context_set_drawable(GDK_WINDOW_XWINDOW((th->da)->window));
	     	imlib_context_set_image(im[1]);
       	     	if (im[1] != NULL) {
		     	gdk_window_clear((th->da)->window);
		     	imlib_render_image_on_drawable_at_size(0,0,24,24);
		}
	}
     
     	return;
}

static void on_throbber_click(GtkWidget *b, Throbber *th)
{
     	g_return_if_fail(th->ss != NULL);
     	home_page = skipstone_get_config_value_as_str("Throbber","HomePage");
     	if (home_page)
       		skipstone_load_url(th->ss, home_page);

     	return;
}

static gint custom_find( gchar *list_value, gchar *user_value )
{
     	return ( strcmp( list_value, user_value ) );
}
static gboolean is_tdir_present( gchar *value )
{
     	if ( g_list_find_custom( tdir_list, value, (GCompareFunc)custom_find ) == NULL ) 
       	 	return FALSE; 
     	return TRUE;
}
static void set_tdir_list()
{

     	gchar *throbDir = g_strconcat( g_get_home_dir(), THROB_BASE_DIR,NULL );
     	DIR *dir;
     	struct dirent *dent;
     	struct stat entryStat;

     	if (tdir_list != NULL) {
	     	GList *l;
	     	for (l = tdir_list; l ; l = l->next) {
		     gchar *data = (gchar *)l->data;
		     if (data) g_free(data);
		}
	     	g_list_free(tdir_list);
	     	tdir_list=NULL;
	}
     	
     	dir = opendir( throbDir );

     	if ( dir ) {
	     	while( ( dent = readdir( dir ) ) ) {
		     	gchar *fileName = g_strconcat( throbDir,"/",dent->d_name,NULL );
		     	stat( fileName, &entryStat );

		     	if ( !S_ISDIR( entryStat.st_mode ) ) {
			     g_free( fileName );
			     	continue;
			}
		     	
		     	if ( !strcmp( dent->d_name, "." ) || !strcmp( dent->d_name, ".." ) ) {
			     	g_free( fileName );
			     	continue;
			}
	  
		     	tdir_list = g_list_append( tdir_list, g_strdup(dent->d_name) );
		     	g_free(fileName);

		}
	     	closedir(dir);

	}
     	g_free(throbDir);
     	return;
}

static GtkWidget *create_config(void)
{
     	GtkWidget *retval, *interval, *homepage, *homelabel,
       		   *intervallabel, *hbox;

     	GtkWidget *throbCombo, *throbLabel, *addLabel;
     	gchar *text, *addText;
     
     	retval = gtk_vbox_new(FALSE,5);
     	homepage=gtk_entry_new();
     	interval=gtk_entry_new();
     	homelabel=gtk_label_new("HomePage: ");
     	intervallabel=gtk_label_new("Animation Interval: ");
     	throbLabel=gtk_label_new("Throbbers: ");
     	throbCombo = gtk_combo_new();
	 
     	set_tdir_list();

     	gtk_combo_set_popdown_strings( GTK_COMBO(throbCombo), tdir_list) ;

     	hbox = gtk_hbox_new(FALSE,5);
     	gtk_box_pack_start(GTK_BOX(hbox), homelabel, FALSE,FALSE, 0);
     	gtk_box_pack_start(GTK_BOX(hbox), homepage, TRUE, TRUE, 0);
     	gtk_box_pack_start(GTK_BOX(retval), hbox, FALSE, FALSE, 0);
     
     	hbox = gtk_hbox_new(FALSE, 5);
     	gtk_box_pack_start(GTK_BOX(hbox), intervallabel, FALSE, FALSE, 0);
     	gtk_box_pack_start(GTK_BOX(hbox), interval, TRUE, TRUE, 0);
     	gtk_box_pack_start(GTK_BOX(retval), hbox, FALSE, FALSE, 0);
     
     	hbox = gtk_hbox_new(FALSE, 5);
     	gtk_box_pack_start(GTK_BOX(hbox), throbLabel, FALSE, FALSE, 0);
     	gtk_box_pack_start(GTK_BOX(hbox), throbCombo, TRUE, TRUE, 0);
     	gtk_box_pack_start(GTK_BOX(retval), hbox, FALSE, FALSE, 0);

     	addText = g_strdup_printf("Place additional throbbers in\n %s%s",g_get_home_dir(), THROB_BASE_DIR);	 
     	addLabel = gtk_label_new(addText);
     	g_free(addText);
     	gtk_box_pack_start(GTK_BOX(retval), addLabel, FALSE, FALSE, 0);
     
     
     	gtk_entry_set_text(GTK_ENTRY(homepage),
			   	skipstone_get_config_value_as_str("Throbber","HomePage"));
     	text = g_strdup_printf("%d",skipstone_get_config_value_as_int("Throbber","Interval"));
     	gtk_entry_set_text(GTK_ENTRY(interval), text);
     	g_free(text);
     
     	gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(throbCombo)->entry), 
			   	skipstone_get_config_value_as_str("Throbber","ThrobDir"));


     /* to get the values later when skipstone passes back the widget for
      * saving */
     	gtk_object_set_data(GTK_OBJECT(retval),"homepage",homepage);
     	gtk_object_set_data(GTK_OBJECT(retval),"interval",interval);
     	gtk_object_set_data(GTK_OBJECT(retval),"throb_combo",throbCombo);
     
     	gtk_widget_show_all(retval);
     	return retval;
}
     

static gint timeout(Throbber *th)
{
     	g_return_val_if_fail(th != NULL, FALSE);
     	g_return_val_if_fail(th->ss != NULL, FALSE);
     	g_return_val_if_fail(th->da != NULL, FALSE);
	g_return_val_if_fail(th->timer != 0, FALSE);
	
     	if (!GTK_IS_DRAWING_AREA(th->da)) {
	     gtk_timeout_remove(th->timer);
	     th->timer = 0;
	     return FALSE;
	}
     	
     	if (skipstone_is_loading(th->ss)) {
       		spin(th);
		th->spining = 1;
     	} else {
		if (th->spining) {
		     	stop(th);
		     	th->spining = 0;
		}		     
	}
     	
     	return TRUE;
}

static void create_plugin(SkipStone *ss)
{
     	Throbber *th;
     	gint interval;

     	th = g_new0(Throbber,1);
     	th->pos = 0;
     	th->spining = 0;
     	th->ss = ss;
     	th->da = gtk_drawing_area_new();
     	th->button = gtk_button_new();     
     	gtk_button_set_relief(GTK_BUTTON(th->button), GTK_RELIEF_NONE);
     	gtk_drawing_area_size(GTK_DRAWING_AREA(th->da),24,24);


     	gtk_signal_connect(GTK_OBJECT(th->da), "destroy",
			   GTK_SIGNAL_FUNC(on_throbber_destroy),
			   th);
     
     	gtk_signal_connect(GTK_OBJECT(th->da), "expose_event",
			   GTK_SIGNAL_FUNC(on_expose),
			   th);
     	gtk_signal_connect(GTK_OBJECT(th->da), "realize",
			   GTK_SIGNAL_FUNC(init_imlib_and_load_files),
			   th);
     	gtk_signal_connect(GTK_OBJECT(th->button), "clicked",
			   GTK_SIGNAL_FUNC(on_throbber_click),
			   th);
						  
     	gtk_container_add(GTK_CONTAINER(th->button), th->da);
     	gtk_widget_show_all(th->button);
     	skipstone_add_plugin_to_toolbar(th->ss, th->button, "Throb on to muhri.net :)");
     	interval = skipstone_get_config_value_as_int("Throbber","Interval");
     	if (!interval || interval == -1) {
	     	interval = 100;
	     	skipstone_set_config_value_as_int("Throbber","Interval",100);
	}
     	th->timer = gtk_timeout_add(interval,(GSourceFunc)timeout, th);
     	throbber_list = g_slist_append(throbber_list, th);
}

static void on_throbber_destroy(GtkWidget *da, Throbber *th)
{
     	if (th->timer)
       		gtk_timeout_remove(th->timer);
     	th->timer = 0;
     	throbber_list=g_slist_remove(throbber_list, th);
     	g_free(th); /* and bye */
     	th = NULL;
}

SkipStonePlugin * init_plugin(void)
{

     	home_page = skipstone_get_config_value_as_str("Throbber","HomePage");
     	if (home_page == NULL) {
	     	/* set our defaults cause appearntly it wasn't set before since skip couldnt find it */
	     	skipstone_set_config_value_as_str("Throbber","HomePage","http://www.muhri.net");
	     	skipstone_set_config_value_as_str("Throbber","ThrobDir",DEFAULT_THROB);
	     	skipstone_set_config_value_as_int("Throbber","Interval",100);
	}
     	return &plugin;
}

static void spin(Throbber *th)
{
     	g_return_if_fail(th != NULL);
     	g_return_if_fail(th->da != NULL);
     	g_return_if_fail(th->timer != 0);
     	g_return_if_fail(th->ss != NULL);
     
     	if (!GTK_IS_DRAWING_AREA(th->da)) {
	     	gtk_timeout_remove(th->timer);
	     	th->timer = 0;
	     	return;
	}
     	
     
     	imlib_context_set_drawable(GDK_WINDOW_XWINDOW((th->da)->window));
     	if (th->pos > num_files) th->pos = 0;
     	th->pos++;
     	if (im[th->pos] == NULL) th->pos = 0;
     	imlib_context_set_image(im[th->pos]);
     	if (im[th->pos] != NULL) {
	     	gdk_window_clear((th->da)->window);
	     	imlib_render_image_on_drawable_at_size(0,0,24,24);
	}
}

static void stop(Throbber *th)	  
{

     	imlib_context_set_drawable(GDK_WINDOW_XWINDOW((th->da)->window));
     	imlib_context_set_image(im[0]);
     	gdk_window_clear((th->da)->window);
     	imlib_render_image_on_drawable_at_size(0,0,24,24);
}

static void load_images()
{
     	gint i;
     	gchar *rest;
     	struct stat buf;
	g_return_if_fail(throbdir != NULL);
     
     	for (i = 1; ; ++i) {
	     	gchar *image;
	     	if (i < 10) 
	    		image = g_strdup_printf("%s/00%d.png",throbdir,i);
	     	else
	       		image = g_strdup_printf("%s/0%d.png",throbdir,i);
	     	if (stat (image, &buf) == 0 && S_ISREG(buf.st_mode)) {
		     	im[i] = imlib_load_image(image);
		     	g_free(image);
		     	imlib_context_set_image(im[i]);
		     	imlib_image_set_has_alpha(imlib_image_has_alpha());
		} else {
		     	g_free(image);
		     	break;
		}
	     	num_files=i;
	}
     	rest = g_strdup_printf("%s/rest.png",throbdir);
     	if (stat (rest, &buf) == 0 && S_ISREG(buf.st_mode)) {
	     	im[0] = imlib_load_image(rest);
	}
     	g_free(rest);
}
           
static void set_throbdir(void)
{
	if (throbdir != NULL) g_free(throbdir);     
     	throbdir = g_strconcat(g_get_home_dir(),THROB_BASE_DIR,"/",
			       skipstone_get_config_value_as_str("Throbber","ThrobDir"),
			       NULL );
}
static void init_imlib_and_load_files(GtkWidget *da, GdkEvent *event, Throbber *th)
{
     	static gint loaded = 0;
     	
     	if (loaded) return;     
     	set_throbdir();
     	if (!throbdir) return;
     
     	imlib_context_set_display(GDK_WINDOW_XDISPLAY(da->window));
     	imlib_context_set_drawable(GDK_WINDOW_XWINDOW(da->window));
     	imlib_context_set_visual(GDK_VISUAL_XVISUAL(gdk_window_get_visual(da->window)));
     	imlib_context_set_colormap(GDK_COLORMAP_XCOLORMAP(gdk_window_get_colormap(da->window)));

     	load_images();
     	loaded = 1;
     	return;
}

static void free_images(void)
{
     gint i;
     for (i = 0; i < 35; ++i){
	  if (im[i] != NULL) {
	       imlib_context_set_image(im[i]);
	       imlib_free_image_and_decache();
	       im[i]=NULL;
	  } else {
	       continue;
	  }
     }
     return;
}
