/* copyright 	Maher Awamy <muhri@muhri.net>		*
 *		Charlie Schmidt <ishamael@themes.org>	*
 *							*
 *  released under the GPL				*/


#include "skipstone.h"




static gint plugins_read = 0;
static GSList *plugin_list = NULL, *plugin_names=NULL;
static PLUGIN_POS pack_position = PLUGIN_AFTER_TOOLBAR; /* default position */

GSList *plugins = NULL;
GHashTable *skipstone_plugin_config = NULL;

extern GSList *history;
extern gchar *home;

gboolean skipstone_plugin_is_enabled(gchar *name);

static void skipstone_read_plugins(void);
static void skipstone_read_plugin_config(void);
static void skipstone_init_plugin_config(void);
static gboolean skipstone_plugin_is_dupe(gchar *name);
static gchar *skipstone_get_concated_key(gchar *plugin_name, 
						gchar *key,
						gint integer);



void skipstone_plugin_check(SkipStone *skipstone, PLUGIN_POS current_position)
{
	GSList *l;
     	D_ENTER;     
     	g_return_if_fail(skipstone != NULL);
     
	pack_position = current_position;
	
	if (!plugins_read) {
		skipstone_read_plugins();
		plugins_read = 1;
	} 
	
     	if (!plugins) D_RETURN;
     
	for (l = plugins; l; l = l->next) {
		SkipStonePlugin *plugin = (SkipStonePlugin *)l->data;
	  if (plugin->in_each_window && plugin->position == current_position)
		  plugin->create_plugin(skipstone);
	}
     
	D_RETURN;
}

static gboolean skipstone_plugin_is_dupe(gchar *name)
{
     GSList *l;
     if (plugin_names == NULL) {
	  	plugin_names = g_slist_append(plugin_names,g_strdup(name));
	  	D_RETURN_( FALSE );
     }
     for (l = plugin_names; l ; l = l->next)
       {
	    if (!g_strcasecmp((gchar *)l->data, name))
	      	D_RETURN_( TRUE );
       }
     plugin_names = g_slist_append(plugin_names, g_strdup(name));
     D_RETURN_ ( FALSE );
}

gboolean skipstone_plugin_is_enabled(gchar *name)
{
   gint x;
   gchar *key;
   key = g_strdup_printf("%s-Enabled",name);
   x = skipstone_get_config_value_as_int("SkipStoneInternal",key);
   if (x == -1) 
     {
	skipstone_set_config_value_as_int("SkipStoneInternal",key,1);
	g_free(key);
	D_RETURN_(TRUE);
     }
   else if (x == 0) 
     {
	g_free(key);
	D_RETURN_(FALSE);
     }
   g_free(key);
   D_RETURN_(TRUE);
}

static void skipstone_read_plugins(void)
{
	GSList *l;	
	gchar *dirname;
	DIR *dir;
	struct dirent *dent;
	gchar *so;
     	gint i;
     	gchar *dirs[] = { 0,
	       		  SKIPSTONE_LOCAL_PLUGIN_DIR, 
	       		  SKIPSTONE_SYSTEM_PLUGIN_DIR,
	       		  NULL
			};	
     	D_ENTER;
	
     	dirs[0] = g_strconcat(home,"/",".skipstone/plugins",NULL);
	for (i = 0; dirs[i] != NULL; ++i) {
	     	dirname = dirs[i];
	     	dir = opendir(dirname);		
	     	if (dir) {		      
			while ((dent = readdir(dir))) {
				if (dent->d_name[0] != '.' && dent->d_ino > 0
				    && (so = strchr(dent->d_name, '.')) != NULL &&
				    !strcmp(so, ".so")) {
				     	if (!skipstone_plugin_is_dupe(dent->d_name))	
					         plugin_list = g_slist_append(plugin_list,
								     g_strconcat(dirname,"/",dent->d_name,NULL));
				     	else
				       		g_print(_("SkipStone skipped plugin %s, its already loaded but appears in another location\n"),dent->d_name);
				}
			}
			closedir(dir);
		}
	}
	g_free(dirs[0]);
	if (!plugin_list) D_RETURN;
		
	skipstone_init_plugin_config(); /* init the hash table */
	skipstone_read_plugin_config(); /* read the config so that plugins can 
					 * set stuff before they are called
					 * to create thier widgets */
	
	for (l = plugin_list; l; l=l->next) {
	     SkipStonePlugin *plugin  =	 load_plugin((gchar *)l->data);
	     if (!plugin)
	       	g_print(_("Plugin: \"%s\" was not loaded, moving on!\n"),(gchar *)l->data);;
	}
			  
	D_RETURN;
}


SkipStonePlugin * load_plugin(gchar *plugin_name)
{
	GModule *handle;
	SkipStonePlugin *plugin;
	SkipStonePlugin *(*init_plugin)();
	gboolean test;

     	D_ENTER;

	handle = g_module_open(plugin_name,0);
	

     	if (!handle) {
		g_print(_("Could not load plugin: \"%s\" \nDynamic Loader Error: %s\n"),plugin_name, g_module_error());
		D_RETURN_ ( NULL );
	}
	
	test = g_module_symbol(handle, "init_plugin",(gpointer ) &init_plugin);
	if (!test)
	  {
		  g_print(_("Dynamic loader error while loading plugin: \"%s\":%s\n"),plugin_name,g_module_error());
		  g_module_close(handle);
		  D_RETURN_ ( NULL );
	  }
	plugin = (*init_plugin)();
	if (!plugin)
	  {
		  g_print(_("SkipStone encountered an error when initilizing plugin: \"%s\"\n"),plugin_name);
		  g_module_close(handle);
		  D_RETURN_ ( NULL );
	  } 

	if (skipstone_plugin_is_enabled(plugin->name))
		plugins = g_slist_append(plugins, plugin);
	else 
	{
		SkipStonePlugin *fake = g_new0(SkipStonePlugin, 1);
		fake->name = g_strdup(plugin->name);
		g_module_close(handle);
		plugins = g_slist_append(plugins,fake);
		D_RETURN_(fake);
	
	}
   
	D_RETURN_ ( plugin );
}
	
gboolean skipstone_is_loading(SkipStone *skipstone)
{

     	g_return_val_if_fail(skipstone != NULL,FALSE);
	return skipstone->is_loading;
}

void skipstone_pack_plugin(SkipStone *skipstone, GtkWidget *plugin)
{
	D_ENTER;
     	g_return_if_fail(skipstone != NULL);
	g_return_if_fail(plugin != NULL);
	g_return_if_fail(skipstone->vbox != NULL);

	if (pack_position == PLUGIN_AFTER_TOOLBAR || pack_position == PLUGIN_AFTER_MOZEMBED || pack_position == PLUGIN_AFTER_STATUSBAR)	
	  gtk_box_pack_start(GTK_BOX(skipstone->vbox),
			     plugin,
			     FALSE,
			     FALSE,
			     0);
	if (pack_position == PLUGIN_RIGHT_OF_MOZEMBED)
	  gtk_box_pack_start(GTK_BOX(skipstone->right_of_embed_box),
			     plugin,
			     FALSE,
			     FALSE,
			     0);
	if (pack_position == PLUGIN_LEFT_OF_MOZEMBED)
	  gtk_box_pack_start(GTK_BOX(skipstone->left_of_embed_box),
			     plugin,
			     FALSE,
			     FALSE,
			     0);
	
	D_RETURN;
}

void skipstone_add_plugin_to_toolbar(SkipStone *skipstone, GtkWidget *plugin,
				     gchar *tip_text)
{
     D_ENTER;
     g_return_if_fail(skipstone != NULL);
     g_return_if_fail(plugin != NULL);
     g_return_if_fail(skipstone->toolbar != NULL);


     gtk_toolbar_append_widget(GTK_TOOLBAR(skipstone->toolbar),
			       plugin,
			       tip_text,
			       tip_text);
     D_RETURN;
}

GSList *skipstone_get_history(void)
{
     D_ENTER;
     D_RETURN_( g_slist_copy(history) );
}

void skipstone_queue_resize(SkipStone *skipstone)
{
     D_ENTER;
     g_return_if_fail(skipstone != NULL);
     gtk_container_resize_children(GTK_CONTAINER(skipstone->vbox));
     D_RETURN;
}

void skipstone_load_url_cb(SkipStone *skipstone, gchar *url)
{
     D_ENTER;
     g_return_if_fail(skipstone != NULL);
     g_return_if_fail(url != NULL);
     _skipstone_load_url(skipstone, url);
     D_RETURN;
}

void skipstone_new_window(gchar *url)
{
     	D_ENTER;
	make_window(url);
     	D_RETURN;
}      


/* config stuff */

void skipstone_write_plugin_config(gpointer key, gpointer value, 
				   gpointer user_data)
{
     gchar *is_int = NULL;
     gchar *real_key=NULL, *plugin_name = NULL;
     gint seperator;
     FILE *config;
     D_ENTER;
     g_return_if_fail(key != NULL);
     g_return_if_fail(user_data != NULL);
     
     config = (FILE *)user_data;
     is_int = strstr((gchar *)key,"$$$");
     
     if (!is_int) 
       	seperator = '&';
     else
       	seperator = '$';

     if (!is_int) g_return_if_fail(value != NULL);
		  
     real_key=strrchr((gchar *)key,seperator);
     real_key++;
     plugin_name = strchr((gchar *)key,seperator);
     if (plugin_name) *plugin_name = '\0';
     if (!is_int) {
/*	  g_print("charechter value %s from plugin name %s and key %s\n",
		  (gchar *)value,(gchar *)key,real_key);*/
	  fprintf(config,"plugin_config: %s`char`%s`%s\n",
		  (gchar *)key,(gchar *)real_key,(gchar *)value);
     } else {
/*	  g_print("integer value %d from plugin name %s and key %s\n",
		  GPOINTER_TO_INT(value),(gchar *)key,real_key);*/
	  fprintf(config,"plugin_config: %s`int`%s`%d\n",
		  (gchar *)key, (gchar *)real_key, GPOINTER_TO_INT(value));
     }
     D_RETURN;
}


static void skipstone_read_plugin_config(void)
{
     gchar *file_name;     
     gchar *line;
     FILE *config;
     file_name=g_strconcat(home,"/.skipstone/plugin_config",NULL);
     D_ENTER;
     config = fopen(file_name,"r");
     if (config == NULL) {
	  	g_free(file_name);	  
	  	D_RETURN;
     }
     line = (gchar *)g_malloc(1024);
     while (fgets(line,1024,config) != NULL)
       {
	    /* plugin_config: plugin_name`type`key`value */
	    line = g_strstrip(line);		
	    if (!strncmp(line,"plugin_config:",14)) {		 
		 gchar  *type = NULL;
		 gchar **splitted = NULL;
		 gint val = 0, is_int = 0;
		 
		 line +=15;
		 
		 splitted = g_strsplit(line, "`", 4);

		 type = splitted[1];
		 if (!strcmp(type,"int")) is_int = 1;
		 
		 if (is_int) 
		   	val = atoi(splitted[3]);

		 if (is_int) {
/*		        g_print("SkipStone is setting config for plugin
				  %s, %s, with value %d as integer\n",
				plugin_name, key, val);*/
		   	skipstone_set_config_value_as_int(splitted[0],
							  splitted[2],
							  val);
		 } else {
		   /* g_print("skipstone is settting config for pluign %s,
			     %s, with value %s as char\n",
			   plugin_name, key, value);*/
		      skipstone_set_config_value_as_str(splitted[0],
							  splitted[2],
							  splitted[3]);
		 }
		 line -= 15;
		 g_strfreev(splitted);
	    }
       }
     fclose(config);
     g_free(line);	    
     g_free(file_name);
     D_RETURN;
}
		
static void skipstone_init_plugin_config(void)
{
     D_ENTER;
     skipstone_plugin_config = g_hash_table_new(g_str_hash, g_str_equal);
     D_RETURN;
}

static gchar *skipstone_get_concated_key(gchar *plugin_name, gchar *key, gint integer)
{
     gchar *seperator = NULL, *retval = NULL;
     D_ENTER;
     if (integer)
       	seperator = "$$$";
     else
       	seperator = "&&&";
     retval = g_strconcat(plugin_name, seperator, key, NULL);
     D_RETURN_ ( retval );
}

void skipstone_set_config_value_as_int(gchar *plugin_name,
				       gchar *key,
				       gint value)
{ 	
     gchar *real_key=NULL;
     D_ENTER;
     g_return_if_fail(plugin_name != NULL);
     g_return_if_fail(key != NULL);

     real_key = skipstone_get_concated_key(plugin_name, key, 1);
     if (real_key) {
	     gconstpointer lookup_key;
	     gpointer orig_key, orig_value;
	     lookup_key = real_key;
	     if (g_hash_table_lookup_extended(skipstone_plugin_config,lookup_key,
					      &orig_key, &orig_value)) {
	/*		     g_print("The key exists and its %s so will replace it with %s\n",
			     (gchar *)orig_key, (gchar *)real_key);*/
		  g_hash_table_insert(skipstone_plugin_config, orig_key, GINT_TO_POINTER(value));
		  g_free(real_key);
	     } else {
/*		  g_print("key %s doesnt exist inserting\n",real_key);*/
		  g_hash_table_insert(skipstone_plugin_config, real_key, GINT_TO_POINTER(value));
	     }
     }
     D_RETURN;
}

void skipstone_set_config_value_as_str(gchar *plugin_name,
				       gchar *key,
				       gchar *value)
{
     gchar *real_key=NULL;
     D_ENTER;
     g_return_if_fail(plugin_name != NULL);
     g_return_if_fail(key != NULL);
     real_key = skipstone_get_concated_key(plugin_name, key, 0);
     if (real_key) {
	     gconstpointer lookup_key;
	     gpointer orig_key, orig_value;
	     lookup_key = real_key;
	     if (g_hash_table_lookup_extended(skipstone_plugin_config,lookup_key,
					      &orig_key, &orig_value)) {
/*		     g_print("set_config_value_as_str() key existed freeing %s! and setting it to %s\n",(gchar *)orig_value,(gchar *)value);*/
		     g_free(orig_value);
		     g_hash_table_insert(skipstone_plugin_config, orig_key, g_strdup(value));
		     g_free(real_key);
	     } else {
/*		     g_print("setting for the first time key %s and value %s\n",real_key,value);*/
		     g_hash_table_insert(skipstone_plugin_config, real_key, g_strdup(value));
	     }
     }
     D_RETURN;
}
	
gchar *skipstone_get_config_value_as_str(gchar *plugin_name, gchar *key)
{
     gchar *real_key=NULL, *retval = NULL;
     D_ENTER;
     g_return_val_if_fail(plugin_name != NULL, NULL);
     g_return_val_if_fail(key != NULL, NULL);
     
     real_key = skipstone_get_concated_key(plugin_name, key, 0);
     if (real_key) {
	     retval = g_hash_table_lookup(skipstone_plugin_config, real_key);
/*	     g_print("looked up %s and found %s\n",(gchar *)real_key,(gchar *)retval);*/
	     g_free(real_key);
     }
     D_RETURN_ ( retval );
}

gint skipstone_get_config_value_as_int(gchar *plugin_name, gchar *key)
{
     gchar *real_key=NULL;
     gint retval = -1;	
     D_ENTER;
     g_return_val_if_fail(plugin_name != NULL, 0);
     g_return_val_if_fail(key != NULL, 0);
     real_key = skipstone_get_concated_key(plugin_name, key, 1);
     if (real_key) {
	     gconstpointer lookup_key;
	     gpointer orig_key, value;
	     lookup_key = real_key;
		if (g_hash_table_lookup_extended(skipstone_plugin_config, lookup_key,
						 &orig_key,&value)) {
/*			g_print("Integer value exists\n");*/
			retval = GPOINTER_TO_INT(value);
		}
	  	g_free(real_key);
     }
     D_RETURN_ ( retval );
}					 

void skipstone_error_dialog(gchar *title, gchar *error, gboolean modal)
{
     D_ENTER;
     create_dialog(title, error, 0, modal);
     D_RETURN;
}
