// This is the ALPHA revision of RPTracker for Gnome.  READ MOST OF THE BELOW, PLEASE
//
// For screenshots:
// http://www.ringworld.net/~dieman/screenshots/tracker1.jpg
// http://www.ringworld.net/~dieman/screenshots/tracker2.jpg
// http://www.ringworld.net/~dieman/screenshots/tracker3.jpg
//
// compile it with:
// gcc `gnome-config --cflags --libs vfs applets` -lpcre -otracker tracker.c
//
// You *neeed* to have gnome-vfs, gnome, xosd, libpcre, and a few other things installed
// as -dev packages to make this work. 
//
// You can view the song as a tooltip by hovering over the icon.  The links in the
// context menu work also.
//
// The song history works.  URL handling is done via gnome.
//
// I disabled xosd popups because they were misbehaving.  I need to figure out how to do
// this without fucking up gtk.
// 
// I need to add more PREFS for the popup.  Look below at FONT, POS, OFFSET.
// I also need to add a timeout, which needs to munge a few values.  xosd sucks, but
// it sucks less than the alternatives.
//
// The next revision will have an actual makefile, some nicer features, etc.
//
// Theres probally a memory leak somewhere, This is probally my first 'venture' into
// 'complicated' programming without a GC.
//
// Feel free to write bugreports to dieman@ringworld.org
//
// RPTracker (C) 2001 Scott M. Dier <dieman@ringworld.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//


#include <gnome.h>
#include <libgnomevfs/gnome-vfs.h>
#include <applet-widget.h>
#include <pcre.h>
#include <stdio.h>
//#include "xosd.h"

#define VERSION ".0.2.1"

//#define DEBUG

#define FONT "fixed"
#define POS 845
#define OFFSET 1

static char *xpm_data[] = {
"22 22 34 1",
" 	c None",
".	c #FFFFFF",
"+	c #394089",
"@	c #23317B",
"#	c #192A79",
"$	c #302E64",
"%	c #102070",
"&	c #04186E",
"*	c #4C3F57",
"=	c #6A5255",
"-	c #784319",
";	c #4B2A12",
">	c #35223C",
",	c #655D99",
"'	c #B39181",
")	c #A96F5F",
"!	c #CE6B1E",
"~	c #A35E1F",
"{	c #FEE462",
"]	c #FCC542",
"^	c #150D0D",
"/	c #F3AE36",
"(	c #FEDBA5",
"_	c #C58D2D",
":	c #D2A43E",
"<	c #E9B2D1",
"[	c #B49BC5",
"}	c #D3A49B",
"|	c #F8A762",
"1	c #8E79B3",
"2	c #F09129",
"3	c #FEE4E4",
"4	c #6D5FBC",
"5	c #1540AB",
"                      ",
"                      ",
" +@@@@#@@$$$@@#@@@@@@+",
" @%%&&@*=-;;>>>%&&%%%@",
" @%%%,')!~;-~!!~->&%%@",
" @&%,'{]!;;^~/]]]~~&%@",
" @&,()~~-;^^_:_~~_]*&@",
" ##<))-^^^^^^^^-~_~:%#",
" #,()~;;;;^^^____::{*#",
" #[(]/----^^^/]]{{{{,#",
" @}(|/!!!-^^^///]{{(1#",
" @}{2!~~!-^^^~)))((31#",
" #'{!~---^^^^;)'}<<3,#",
" #={2~;;-^^;^^111[<<@#",
" #%:2!-;-;;>>&444[31&@",
" @&*/22~--*>++4<<33#&@",
" @%&2!~~;)$%%54<33<&%@",
" @%%&$>^$5#%4[1[1#&%%@",
" @%%%&%%#4+#[}+%&&%%%@",
" +@@@@@@@@@@+@##@@@@@+",
"                      ",
"                      "};

gint popup = FALSE;
GtkWidget *prop1;
GtkWidget *pref_popup;
GtkWidget *applet;
GtkTooltips *tips;

pcre *pattern1;
pcre_extra *hints1;

char song[4][1024];
char url[4][1024];

static void on_propertybox1_apply();
static void on_pref_change();
static void last4_close();
static void show_url(GtkWidget *a,gpointer b);
static void dialog_close(GtkWidget *a,gpointer b);
static int rp_check();

GtkWidget*
create_propertybox1 (void)
{
GtkWidget *propertybox1;
GtkWidget *notebook1;
GtkWidget *label1;

propertybox1 = gnome_property_box_new ();
gtk_widget_set_name (propertybox1, "propertybox1");
gtk_object_set_data (GTK_OBJECT (propertybox1), "propertybox1", propertybox1);
gtk_window_set_policy (GTK_WINDOW (propertybox1), FALSE, FALSE, FALSE);

notebook1 = GNOME_PROPERTY_BOX (propertybox1)->notebook;
gtk_widget_set_name (notebook1, "notebook1");
gtk_object_set_data (GTK_OBJECT (propertybox1), "notebook1", notebook1);
gtk_widget_show (notebook1);

pref_popup = gtk_check_button_new_with_label (_("Use a notification popup when a song change is detected."));
gtk_widget_set_name (pref_popup, "pref_popup");
gtk_widget_ref (pref_popup);
gtk_object_set_data_full (GTK_OBJECT (propertybox1), "pref_popup", pref_popup,
(GtkDestroyNotify) gtk_widget_unref);
if(popup==TRUE) {
	((GtkToggleButton *)pref_popup)->active=TRUE;
} else {
	((GtkToggleButton *)pref_popup)->active=FALSE;
}
gtk_widget_show (pref_popup);
gtk_container_add (GTK_CONTAINER (notebook1), pref_popup);
gtk_signal_connect (GTK_OBJECT(pref_popup), "toggled", GTK_SIGNAL_FUNC(on_pref_change),NULL);

label1 = gtk_label_new (_("Properties"));
gtk_widget_set_name (label1, "label1");
gtk_widget_ref (label1);
gtk_object_set_data_full (GTK_OBJECT (propertybox1), "label1", label1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label1);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 0), label1);

gtk_signal_connect (GTK_OBJECT (propertybox1), "apply",
GTK_SIGNAL_FUNC (on_propertybox1_apply),
NULL);

return propertybox1;
}

static gint applet_save_session(GtkWidget *w, const char *privcfgpath,
		const char *globcfgpath) {
	gnome_config_push_prefix(privcfgpath);
	gnome_config_set_bool("prefs/popup",popup);
	gnome_config_pop_prefix();
	gnome_config_sync();
	gnome_config_drop_all();
	return FALSE;
}

static void last4 (AppletWidget *applet, gpointer data) {
	// I need to show a window with 4 GtkButton's with labels for songs and 
	// actions for those labels.  Close the window after a button is pressed.
	//
	
	GtkWidget *dialog;
	GtkWidget *button[4];
	GPtrArray *pointers;
	int i=0;

	dialog = gnome_dialog_new ("RPTracker: Last 4 Songs",
			GNOME_STOCK_BUTTON_CLOSE,
			NULL);
	gnome_dialog_set_close((GnomeDialog *)dialog,TRUE);

	for(i=0;i<4;i++) {
		button[i] = gtk_button_new_with_label(song[i]);
		gtk_signal_connect(GTK_OBJECT (button[i]),"clicked",GTK_SIGNAL_FUNC(show_url), url[i]);
		gtk_signal_connect(GTK_OBJECT (button[i]),"clicked",GTK_SIGNAL_FUNC(dialog_close), dialog);
		gtk_box_pack_start(GTK_BOX (GNOME_DIALOG (dialog)->vbox), button[i], TRUE,
				FALSE,0);
		gtk_widget_show(button[i]);
	}

	gtk_window_set_position(GTK_WINDOW(dialog),GTK_WIN_POS_MOUSE);
	gtk_widget_show(dialog);
}


static void rplink (AppletWidget *applet, gpointer data) {
	gnome_url_show("http://www.radioparadise.com/");
}
static void rpsong (AppletWidget *applet, gpointer data) {
	gnome_url_show(g_strconcat("http://www.radioparadise.com/",url[0]));
}

static void props (AppletWidget *applet, gpointer data) {
	prop1 = create_propertybox1();
	gtk_widget_show(prop1);
}

static void on_propertybox1_apply() {
	if(((GtkToggleButton *)pref_popup)->active==TRUE) {
		popup=TRUE;
	} else {
		popup=FALSE;
	}
	applet_widget_sync_config((AppletWidget *)applet);
}

static void on_pref_change() {
	gnome_property_box_changed((GnomePropertyBox *)prop1);
}

static void show_url(GtkWidget *a, gpointer b) {
	gnome_url_show(g_strconcat("http://www.radioparadise.com/",b));
}

static void dialog_close(GtkWidget *a, gpointer b) {
	gnome_dialog_close(b);
}

static void aboutdlg (AppletWidget *applet, gpointer data) {
	const gchar *authors[] = {
		"Scott M. Dier <dieman@ringworld.org>",
		NULL
	};

	gtk_widget_show (gnome_about_new ("RPTracker",VERSION,
				"Copyright 2001 Scott M. Dier",
				(const gchar **) authors,
				_("Written to show current song information "
				 "from the Radioparadise website.\n"
				 "This program is free software; you can redistribute it and/or "
				 "modify it under the terms of the GNU General Public License "
				 "as published by the Free Software Foundation; either version 2 "
				 "of the License, or (at your option) any later version. "
				 "This program is distributed in the hope that it will be useful, "
				 "but WITHOUT ANY WARRANTY; without even the implied warranty of "
				 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
				 "GNU General Public License for more details. "
				 "You should have received a copy of the GNU General Public License "
				 "along with this program; if not, write to the Free Software "
				 "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA."),
				NULL));
}

int main (int argc, char *argv[]) {
	GtkWidget *pixmap;
	const char *error;
	int erroffset;

	applet_widget_init("RPTracker",VERSION,argc, argv, NULL, 0, NULL);

	applet = applet_widget_new("RPTracker");
	if(!applet)
		g_error("Can't create applet!\n");

	gnome_config_push_prefix(APPLET_WIDGET(applet)->privcfgpath);
	popup = gnome_config_get_bool("prefs/popup=true");
	gnome_config_pop_prefix();

	pixmap = gnome_pixmap_new_from_xpm_d(xpm_data);
	gtk_widget_show(pixmap);

	gtk_signal_connect(GTK_OBJECT(applet),"save_session",
			GTK_SIGNAL_FUNC(applet_save_session),
			NULL);

	gtk_signal_connect(GTK_OBJECT(applet),"button_press_event",
		GTK_SIGNAL_FUNC(last4),
		NULL);

	gtk_widget_set_events(applet, gtk_widget_get_events(applet) | \
				GDK_BUTTON_PRESS_MASK);


	applet_widget_add(APPLET_WIDGET (applet),pixmap);
	gtk_widget_show(applet);

	applet_widget_register_stock_callback(APPLET_WIDGET(applet),"last4",
			GNOME_STOCK_MENU_INDEX,
			_("Last Four Songs"),
			last4,
			NULL);
	
	applet_widget_register_stock_callback(APPLET_WIDGET(applet),"gotorp",
			GNOME_STOCK_MENU_JUMP_TO,
			_("Goto RP"),
			rplink,
			NULL);
	
	applet_widget_register_stock_callback(APPLET_WIDGET(applet),"songinfo",
			GNOME_STOCK_MENU_JUMP_TO,
			_("Goto song"),
			rpsong,
			NULL);

	applet_widget_register_stock_callback(APPLET_WIDGET(applet),"props",
			GNOME_STOCK_MENU_PROP,
			_("Properties..."),
			props,
			NULL);

	applet_widget_register_stock_callback(APPLET_WIDGET(applet),"aboutdlg",
			GNOME_STOCK_MENU_ABOUT,
			_("About..."),
			aboutdlg,
			NULL);

	// put something here to run every few seconds to check for a new song
	// title and perhaps a popup if its in the config.  Keep history of the last
	// four songs.
	//
	// Thank god i figured out how the fsck pcre works.
	pattern1 = pcre_compile("(?s)tent=\"(.*?)\".*?<a href=\"..(.*?)\" target.*?\n(.*?)</a>.*?<a href=\"..(.*?)\" target.*?\n(.*?)</a>.*?<a href=\"..(.*?)\" target.*?\n(.*?)</a>.*?<a href=\"..(.*?)\" target.*?\n(.*?)</a>",
			0, &error, &erroffset, NULL);
	hints1 = pcre_study(pattern1,0,&error);
	gnome_vfs_init();

	tips = gtk_tooltips_new();

	//osd = xosd_init(FONT, "LawnGreen" ,5,XOSD_top,POS,OFFSET);

	gtk_timeout_add(50,&rp_check,NULL);
	//rp_check();

	applet_widget_gtk_main();
	return(0);
}

//gboolean kill_osd(gpointer b) {
//	xosd_uninit((xosd *)b);
//	return FALSE;
//}

gboolean rp_check() {
	GnomeVFSHandle *vfshandle;
	GnomeVFSURI *vfsuri;
	GnomeVFSResult result;
	GnomeVFSFileSize bytes_read;
	GnomeVFSFileSize i;
	//xosd *osd;
	int outvec[99];
	int count;
	// if its bigger than this somethings wrong then.
	char buffer[4096];
	char buff2[1024];
#ifdef DEBUG
	g_message("rp_check: vfs-retrieve");
#endif

	vfsuri = gnome_vfs_uri_new("http://www.radioparadise.com/nowplay_frame.php");

	result = gnome_vfs_open_uri(&vfshandle,vfsuri,GNOME_VFS_OPEN_READ);

	if (result != GNOME_VFS_OK) {
		gtk_timeout_add(90000,&rp_check,NULL);
		return FALSE;
	}

	result = gnome_vfs_read(vfshandle,buffer,sizeof(buffer),&bytes_read);

	if (result != GNOME_VFS_OK) {
		gtk_timeout_add(90000,&rp_check,NULL);
		return FALSE;
	}
	buffer[bytes_read]='\0';

#ifdef DEBUG
	        g_message("rp_check: vfs-retrieve done, doing regex1");
#endif

	// ok, ive got this regexp, lets do it.
	
	count = pcre_exec(pattern1,hints1,buffer,bytes_read,0,0,outvec,99);
	if(count != 10) { 
		gtk_timeout_add(90000,&rp_check,NULL);
		return FALSE;
	}
	pcre_copy_substring(buffer, outvec, count, 1, buff2, sizeof(buff2));

#ifdef DEBUG
	        g_message("rp_check: setting next check time");
#endif

	gtk_timeout_add( strtod(buff2,NULL)*1000,&rp_check,NULL);

	pcre_copy_substring(buffer, outvec, count, 2, buff2, sizeof(buff2));
		strncpy(url[0],buff2,sizeof(url[0]));

	pcre_copy_substring(buffer, outvec, count, 3, buff2, sizeof(buff2));
	if(strcmp(song[0],buff2)!=0) {
		gtk_tooltips_set_tip(GTK_TOOLTIPS(tips), applet, buff2, NULL);
		// put hook to show popup here.
		//if(popup==TRUE) {
		//	osd = xosd_init(FONT, "LawnGreen" ,5,XOSD_top,POS,OFFSET);
		//	xosd_display(osd,0,XOSD_string,buff2);
		//	gtk_timeout_add(10000,&kill_osd,osd);
		//}
	}
	strncpy(song[0],buff2,sizeof(song[0]));

	pcre_copy_substring(buffer, outvec, count, 4, buff2, sizeof(buff2));
		strncpy(url[1],buff2,sizeof(url[1]));
	pcre_copy_substring(buffer, outvec, count, 5, buff2, sizeof(buff2));
		strncpy(song[1],buff2,sizeof(song[1]));
	pcre_copy_substring(buffer, outvec, count, 6, buff2, sizeof(buff2));
		strncpy(url[2],buff2,sizeof(url[2]));
	pcre_copy_substring(buffer, outvec, count, 7, buff2, sizeof(buff2));
		strncpy(song[2],buff2,sizeof(song[2]));
	pcre_copy_substring(buffer, outvec, count, 8, buff2, sizeof(buff2));
		strncpy(url[3],buff2,sizeof(url[3]));
	pcre_copy_substring(buffer, outvec, count, 9, buff2, sizeof(buff2));
		strncpy(song[3],buff2,sizeof(song[3]));

#ifdef DEBUG
	        g_message("rp_check: regex3 done, closing vfs");
#endif

	gnome_vfs_close(vfshandle);
	gnome_vfs_uri_unref(vfsuri);
#ifdef DEBUG
	        g_message("rp_check: closed vfs handle");
#endif
	return FALSE;
}
