#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>

#include "callbacks.h"
#include "interface.h"
#include "support.h"

#define AREAW 200
#define AREAH 50
#define AVG_RATE 5

gint graph_in[AREAW]={0};
gint graph_out[AREAW]={0};

/* Keep track of max. peaks */
gint max_in;
gint max_out;

gint avg_in[AVG_RATE]={0};
gint avg_out[AVG_RATE]={0};
gint avg_pos=0;

gint nowgra=0;
gint big=1;
unsigned long bytes_in, bytes_out;
gint timer=0;
extern char interface[6];
char *i;

gboolean thetimer(gpointer data) {
	if (nowgra < AREAW - 1)
		nowgra++;
	else
		nowgra=0;

	updatevalue();
	flash(data);

	return TRUE;
}

void updatevalue() {
	gint n;
	unsigned long stack_in_old, stack_in_new, stack_out_old, stack_out_new;

	stack_in_old = bytes_in;
	stack_out_old = bytes_out;
	getvalue(interface, &bytes_in, &bytes_out);
	stack_in_new = bytes_in;
	stack_out_new = bytes_out;
	graph_in[nowgra] = stack_in_new - stack_in_old;
	graph_out[nowgra] = stack_out_new - stack_out_old;

	/* Keep track of max. peaks */ 
	if (max_in < graph_in[nowgra]) max_in = graph_in[nowgra];
	if (max_out < graph_out[nowgra]) max_out = graph_out[nowgra];

	/* Keep track of average speed */
	avg_in[avg_pos] = graph_in[nowgra];
	avg_out[avg_pos] = graph_out[nowgra];
	avg_pos++;
	if(avg_pos >= AVG_RATE) avg_pos=0;

	big = 1; 
	for (n=0; n < AREAW; n++) {
		if (graph_in[n] > big) big = graph_in[n];
		if (graph_out[n] > big) big = graph_out[n];
	}
}


gint getvalue(char *interface, unsigned long *inb, unsigned long *outb) {
#define BUFSIZE 2048
	FILE *f;
	char buf[BUFSIZE];
	gint num;
	char *pos;
	unsigned long values[16];

	f = fopen("/proc/net/dev", "r");
	if (f == 0)
		printf("Unable to open proc file.\n");
	num = fread(buf, 1, BUFSIZE - 1, f);
	if (ferror(f)) {
		fclose(f);
		printf("Read errors.\n");
		return 0;
	}
	buf[num] = 0;
	fclose(f);

	pos = strstr(buf, interface);
	if (pos == 0) {
		printf("Interface %s not found.\n", interface);
		return 0;
	}
//	pos += strlen(interface);
//	pos++;

	num = sscanf(pos + strlen(interface) + 1,
		  "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
			 &values[0], &values[1], &values[2], &values[3],
			 &values[4], &values[5], &values[6], &values[7],
			 &values[8], &values[9], &values[10], &values[11],
			 &values[12], &values[13], &values[14], &values[15]);

	*inb = values[0];
	*outb = values[8];

	return 1;
}



gboolean flash (GtkWidget  *drawingarea) {
	gint n,p;
	float avg;
	char s[50];
	char slabel[100];  

	GdkDrawable *drawable;
	GdkGC *gc;
	GdkColor color0={0,0x0000,0x0000,0x0000};
	GdkColor color1={0,0xffff,0x5555,0x5555};
	GdkColor color2={0,0x5555,0xffff,0x5555};

	drawable = drawingarea -> window;

	gdk_colormap_alloc_color (gdk_colormap_get_system (), &color0, FALSE, TRUE);
	gc=gdk_gc_new(drawable);
	gdk_gc_set_foreground(gc,&color0);
	gdk_draw_rectangle(drawable, gc, TRUE, 0, 0, AREAW, AREAH);

	gdk_colormap_alloc_color (gdk_colormap_get_system (), &color2, FALSE, TRUE);
	gc=gdk_gc_new(drawable);
	gdk_gc_set_foreground(gc,&color2);
	for (n=1; n < 4; n++)
		gdk_draw_line (drawable, gc, 0, AREAH*n/4 , AREAW, AREAH*n/4); 
	for (n=1; n < 6; n++) 
		gdk_draw_line (drawable, gc, AREAW*n/6, 0, AREAW*n/6, AREAH); 

	gdk_colormap_alloc_color (gdk_colormap_get_system (), &color1, FALSE, TRUE);
	gc=gdk_gc_new(drawable);
	gdk_gc_set_foreground(gc,&color1);

	for (n=0; n < AREAW; n++) {
		p = nowgra - n;
		if (p < 0) p = p + AREAW;  
		gdk_draw_line (drawable, gc, n, AREAH, n, AREAH - graph_in[p] * AREAH / big );
		gdk_draw_line (drawable, drawingarea->style->white_gc, n, AREAH, n,
				AREAH - graph_out[p] * AREAH / big );  
	}


	/* Current speed in */
	strcpy(slabel,"In: ");
	bytebit(graph_in[nowgra], s);
	strcat(slabel, s);

	/* Calculate average in speed */
	avg = 0;
	for(n=0; n < AVG_RATE; n++) {
		avg += avg_in[n];
	}
	avg /= AVG_RATE;
	strcat(slabel, " (");
	bytebit(avg,s);
	strcat(slabel, s);
	strcat(slabel, ")\n");

	/* Max. speed in */
	/*  strcat(slabel, " (");
	bytebit(max_in,s);
	strcat(slabel, s);
	strcat(slabel, ")\n");*/

	/* Current speed out */
	strcat(slabel, "Out: ");
	bytebit(graph_out[nowgra], s);
	strcat(slabel, s);

	/* Max speed out */
	/*strcat(slabel, " (");
	bytebit(max_out, s);
	strcat(slabel, s);
	strcat(slabel, ")");*/

	/* Calculate average out speed */
	avg = 0;
	for(n=0; n < AVG_RATE; n++) {
		avg += avg_out[n];
	}
	avg /= AVG_RATE;
	strcat(slabel, " (");
	bytebit(avg,s);
	strcat(slabel, s);
	strcat(slabel, ")");

	gtk_label_set_text(GTK_LABEL(lookup_widget(GTK_WIDGET (drawingarea), "label2")), slabel);
	gdk_gc_destroy (gc);  

	return TRUE;
}

void bytebit (float f, char *s) {
	char suffix[5];

/*  f = f * 8;
	if (f < 1e3)
		strcpy(suffix, "bps");
	else */
	if (f < 1e6) {
		f = f / 1e3 ;
		strcpy(suffix, "Kbps");
	} else {
		f = f / 1e6 ;
		strcpy(suffix, "Mbps");
	}
	sprintf(s,"%.1f%s",f,suffix);
}

gboolean on_drawingarea1_expose_event  (GtkWidget       *widget,
                                        GdkEventExpose  *event,
                                        gpointer         user_data) {
	if(!timer) {
		timer_init(widget);
	}
 
	flash(lookup_widget(GTK_WIDGET (widget), "drawingarea1"));
	return FALSE;
}


void on_window1_destroy (GtkObject *object, gpointer user_data) {
	gtk_main_quit();
}

void timer_init(GtkWidget *widget) {
	char title[20];

	strcpy(title, "bungmeter (");
    strcat(title, interface);
    strcat(title, ")");
	gtk_window_set_title (GTK_WINDOW (lookup_widget(GTK_WIDGET (widget), "window1")), title);

	getvalue(interface, &bytes_in, &bytes_out);
	timer = gtk_timeout_add(1000, thetimer, lookup_widget(GTK_WIDGET (widget), "drawingarea1"));
}
 
