
#include <stdio.h>
#include <config.h>
#include <applet-widget.h>
#include <ctype.h>
#include "quickrecord_applet.h"
#include "properties.h"
#include "interface.h"
#include "support.h"


static GtkWidget *propbox = NULL;
static gboolean internal = FALSE;   /* If event is internal */


static void set_widgets_from_options(Properties *props);
static void set_buffer_size_label(void);
static void get_options_from_widgets(Properties *props);
void parse_to_printf_string(Properties *props, gchar *str);


/************* CALLBACKS **************/

/*
 * Called when Properties in the menu is clicked. Open one propertybox.
 */
void properties(AppletWidget *applet, gpointer data) {
	Properties *props=(Properties *)data;

	/* only show one property box at a time */
	if (propbox) {
		gdk_window_raise (propbox->window);
		return;
	}

	propbox = create_propertybox();
	internal=TRUE;
	set_widgets_from_options(props);
	internal=FALSE;

	/* connect property box signals */
        gtk_signal_connect(GTK_OBJECT(propbox), "apply",
			   GTK_SIGNAL_FUNC(apply_cb), props);

        gtk_signal_connect(GTK_OBJECT(propbox), "destroy",
			   GTK_SIGNAL_FUNC(destroy_cb), NULL);

        gtk_signal_connect(GTK_OBJECT(propbox), "help",
			   GTK_SIGNAL_FUNC(help_cb), NULL);

	gtk_widget_show(propbox);

        return;
}


/*
 * Apply clicked.
 */
void apply_cb(GnomePropertyBox *propertybox, gint arg1, gpointer data) {
	Properties *props=(Properties *)data;

	get_options_from_widgets(props);

	/* Set the states (sanity checks can change them). */
	internal=TRUE;
	set_widgets_from_options(props);
	internal=FALSE;
	record_set_options(props);

/*	applet_widget_sync_config(applet); */
	return;
}


/*
 * Help!
 */
void help_cb(GnomePropertyBox *propertybox, gint arg1, gpointer data) {
	g_print(_("No help yet.\n"));
	return;
/*
  GnomeHelpMenuEntry help_entry = { "diskusage_applet",
  "index.html#DISKUSAGE-APPLET-PREFS" };
  gnome_help_display(NULL, &help_entry);
  */
}

/*
 * Just allow closure.
 */
gint destroy_cb(GtkObject *object, gpointer data) {
	propbox=NULL;
	return FALSE;
}

/*
 * Called when anything in the propertybox is changed.
 * Enable the apply-button unless internal.
 * Re-sets the buffer size label.
 */
void something_changed(GtkWidget *widget, gpointer user_data) {

	if (!internal)
		gnome_property_box_changed(GNOME_PROPERTY_BOX(propbox));
	set_buffer_size_label();

	return;
}



/*************** HELPER FUNCTIONS **************/

/*
 * Update the widgets to show the option status. Also sets the buffer-size
 * label.
 */
static void set_widgets_from_options(Properties *props) {
	GtkWidget *w;
	gchar buf[1000];

	w=lookup_widget(propbox,"rate_entry");
	snprintf(buf,10,"%d",props->rate);
	gtk_entry_set_text(GTK_ENTRY(w),buf);

	if (props->bits==16)
		w=lookup_widget(propbox,"sixteen_bit_button");
	else
		w=lookup_widget(propbox,"eight_bit_button");
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),TRUE);

	if (props->stereo)
		w=lookup_widget(propbox,"stereo_button");
	else
		w=lookup_widget(propbox,"mono_button");
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),TRUE);

	w=lookup_widget(propbox,"prerec_amount_spin_button");
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),props->prerec_amount);

	w=lookup_widget(propbox,"start_with_prerec_button");
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),props->start_prerec);

	w=lookup_widget(propbox,"source_cd_button");
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
				     props->source&REC_CD);
	w=lookup_widget(propbox,"source_mic_button");
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
				     props->source&REC_MIC);
	w=lookup_widget(propbox,"source_line_button");
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
				     props->source&REC_LINE);

	/* Set the filename */
	w=lookup_widget(propbox,"filename_entry");
	if (props->filestart<0) {
		gtk_entry_set_text(GTK_ENTRY(w),props->filename);
	} else {
		snprintf(buf,900,props->filename,props->filestart);
		gtk_entry_set_text(GTK_ENTRY(w),buf);
	}

	set_buffer_size_label();

	return;
}

/*
 * Sets the buffer size label to correspond the settings.
 */
static void set_buffer_size_label(void) {
	GtkWidget *w;
	Properties props={0};
	gchar buf[100];
	gint n;

	/* Set the buffer_size_label */
	get_options_from_widgets(&props);
	w=lookup_widget(propbox,"buffer_size_label");
	n=props.rate;
	if (props.bits==16)
		n*=2;
	if (props.stereo)
		n*=2;
	n*=props.prerec_amount;
	n=(n+512)/1024;
	if (n>1024) {
		snprintf(buf,90,_("Buffer size approximately %.1f MB"),
			 (gfloat)n/1024);
	} else {
		snprintf(buf,90,_("Buffer size approximately %d kB"),n);
	}
	gtk_label_set_text(GTK_LABEL(w),buf);

	return;
}



/*
 * Read the status of the widgets to *props.
 */
static void get_options_from_widgets(Properties *props) {
	GtkWidget *w;
	gchar *c;
	gint n;

	w=lookup_widget(propbox,"rate_entry");
	c=gtk_entry_get_text(GTK_ENTRY(w));
	n=atoi(c);
	props->rate=CLAMP(n,6000,48000);

	w=lookup_widget(propbox,"sixteen_bit_button");
	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
		props->bits=16;
	else
		props->bits=8;

	w=lookup_widget(propbox,"stereo_button");
	props->stereo=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));

	w=lookup_widget(propbox,"prerec_amount_spin_button");
	props->prerec_amount=
		CLAMP(gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(w)),
		      0.1,100);

	w=lookup_widget(propbox,"start_with_prerec_button");
	props->start_prerec=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));

	n=0;
	w=lookup_widget(propbox,"source_cd_button");
	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
		n|=REC_CD;
	w=lookup_widget(propbox,"source_mic_button");
	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
		n|=REC_MIC;
	w=lookup_widget(propbox,"source_line_button");
	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
		n|=REC_LINE;
	props->source=n;

	w=lookup_widget(propbox,"filename_entry");
	c=gtk_entry_get_text(GTK_ENTRY(w));

	parse_to_printf_string(props,c);

	return;
}

/*
 * Parses either a number-containing string or a printf-style string
 * into props->filename and ->filestart from str.
 */
void parse_to_printf_string(Properties *props, gchar *str) {
	gchar *c;
	gint i,j,n;
	gint start,end;

	/* First check for a %d-string */
	/* TODO FIXME: '%' not allowed in filename */
	start=end=-1;
	for (i=strlen(str); i>=0; i--) {
		if (str[i]=='%') {
			/* Check for 'd' */
			for (j=i+1; str[j]!=0; j++) {
				if (str[j]=='d') {
					start=i;
					end=j;
					break;
				}
				if (!isdigit(str[j])) {
					/* Bad - remove '%'... */
					str[i]='_';
					break;
				}
			}
			if (start>=0)
				break;
		}
	}
	/* Check rest of strings for no more '%' */
	for (i=start-1; i>=0; i--)
		if (str[i]=='%') {
			str[i]='_';
		}

	if (start<0) {
		/* Look for a number instead */
		for (i=strlen(str); i>=0; i--) {
			if (isdigit(str[i])) {
				end=i;
				break;
			}
		}
		while (i>0 && isdigit(str[i-1]))
			i--;
		if (isdigit(str[i]))
			start=i;
	}

	/* Do the stuff...*/
	if (props->filename) {
		g_free(props->filename);
		props->filename=NULL;
	}

	if (start<0) {
		/* No number/printf-notation found. */
		props->filename=g_strdup(str);
		props->filestart=-2;
		return;
	}

	if (str[start]=='%') {
		/* Perfectly valid printf-notation. */
		props->filename=g_strdup(str);
		props->filestart=-1;
		return;
	}

	g_assert(isdigit(str[start]));   /* Should be a digit. */

	/* Shouldn't lengthen more than a few chars */
	c=g_new0(gchar,strlen(str)+30);

	for (i=0; i<start; i++) {
		c[i]=str[i];
	}
	c[i++]='%';
	c[i++]='0';
	snprintf(c+i,20,"%d",end-start+1);
	i=strlen(c);
	c[i++]='d';

	for (j=end+1; str[j]; i++, j++)
		c[i]=str[j];
	props->filename=c;

	/* Get starting value */
	n=0;
	for (i=start; i<=end; i++) {
		n*=10;
		n+=str[i]-'0';
	}
	n=CLAMP(n,0,G_MAXINT-1);
	props->filestart=n;

	return;
}


