#include <stdio.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include <sys/time.h>
#include <unistd.h>


gint timer_callback();
float get_idle(gfloat *, gint *);
gint delete_event(GtkWidget *, GdkEvent *, gpointer);

FILE *loadavd_file, *stat_file;
GtkWidget *load_bar, *idle_bar, *user_bar, *system_bar, *nice_bar;

void main(int argc, char *argv[]) {
   char string[255];

   GtkWidget *load_label, *idle_label, *user_label, *system_label, *nice_label;

   GtkWidget *table;
   
   GtkWidget *window;
   
   gint timer_tag;

   gtk_init(&argc, &argv);

   table = gtk_table_new (5, 2, FALSE);
   
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

   load_label = gtk_label_new("Load");
   system_label = gtk_label_new("System");
   idle_label = gtk_label_new("Idle");
   user_label = gtk_label_new("User");
   nice_label = gtk_label_new("Nice");

   load_bar = gtk_progress_bar_new();
   user_bar = gtk_progress_bar_new();
   nice_bar = gtk_progress_bar_new();
   idle_bar = gtk_progress_bar_new();
   system_bar = gtk_progress_bar_new();

   gtk_container_add(GTK_CONTAINER(window), table);

   gtk_table_attach_defaults(GTK_TABLE(table), load_label, 0, 1, 0, 1);
   gtk_table_attach_defaults(GTK_TABLE(table), load_bar, 1, 2, 0, 1);
   gtk_table_attach_defaults(GTK_TABLE(table), user_label, 0, 1, 1, 2);
   gtk_table_attach_defaults(GTK_TABLE(table), user_bar, 1, 2, 1, 2);
   gtk_table_attach_defaults(GTK_TABLE(table), nice_label, 0, 1, 2, 3);
   gtk_table_attach_defaults(GTK_TABLE(table), nice_bar, 1, 2, 2, 3);
   gtk_table_attach_defaults(GTK_TABLE(table), idle_label, 0, 1, 3, 4);
   gtk_table_attach_defaults(GTK_TABLE(table), idle_bar, 1, 2, 3, 4);
   gtk_table_attach_defaults(GTK_TABLE(table), system_label, 0, 1, 4, 5);
   gtk_table_attach_defaults(GTK_TABLE(table), system_bar, 1, 2, 4, 5);

   gtk_widget_show(table);
   gtk_widget_show(load_bar);
   gtk_widget_show(system_bar);
   gtk_widget_show(nice_bar);
   gtk_widget_show(user_bar);
   gtk_widget_show(idle_bar);

   gtk_widget_show(load_label);
   gtk_widget_show(system_label);
   gtk_widget_show(nice_label);
   gtk_widget_show(user_label);
   gtk_widget_show(idle_label);
   gtk_widget_show(window);

   if((loadavd_file=fopen("/proc/loadavg", "r"))==NULL) {
     fprintf(stderr, "couldn't open load\n");
     exit(-1);
   }

   if((stat_file=fopen("/proc/stat", "r"))==NULL) {
     fprintf(stderr, "couldn't open stat\n");
     exit(-1);
   }

   gtk_timeout_add( 1000, // Interval i msecs. 
			 timer_callback, // callback
			 NULL);
 
   gtk_signal_connect (GTK_OBJECT (window), "delete_event",
		       GTK_SIGNAL_FUNC (delete_event), NULL);
  
   gtk_main();

}

gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
  g_print ("delete event occurred\n");
  /* if you return FALSE in the "delete_event" signal handler,
   * GTK will emit the "destroy" signal.  Returning TRUE means
   * you don't want the window to be destroyed.
   * This is useful for popping up 'are you sure you want to quit ?'
   * type dialogs. */
  
  /* Change TRUE to FALSE and the main window will be destroyed with
   * a "delete_event". */
  gtk_main_quit();
  return (TRUE);
}

gint timer_callback() {
  static struct timeval time_now, time_last;
  int time_elapsed;
  int sigma_jiffies;

  gfloat loadavg[4]; 
  gint jiffies[4];

  gettimeofday(&time_now, NULL);
  time_elapsed=time_now.tv_usec-time_last.tv_usec;
  time_last.tv_usec=time_now.tv_usec;
  fprintf(stderr, "Time elapsed=%i\n", time_elapsed);

  fprintf (stderr, "timeout\n");
  get_idle(loadavg, jiffies);
  sigma_jiffies=jiffies[0]+jiffies[1]+jiffies[2]+jiffies[3];
  
  gtk_progress_bar_update( GTK_PROGRESS_BAR ( load_bar ),
			   loadavg[0]);
  gtk_progress_bar_update( GTK_PROGRESS_BAR ( system_bar ),
			   (gfloat) jiffies[2]/sigma_jiffies);
  gtk_progress_bar_update( GTK_PROGRESS_BAR ( idle_bar ),
			   (gfloat) jiffies[3]/sigma_jiffies);
  gtk_progress_bar_update( GTK_PROGRESS_BAR ( user_bar ),
			   (gfloat) jiffies[0]/sigma_jiffies);
  gtk_progress_bar_update( GTK_PROGRESS_BAR ( nice_bar ),
			   (gfloat) jiffies[1]/sigma_jiffies);
  return TRUE;
}

float get_idle(gfloat *loadavg, gint *jiffies) {

  static gint stat[4], olde_stat[4];

  char dummy[255];
  int count;
  if((loadavd_file=freopen("/proc/loadavg", "r", loadavd_file))==NULL) 
    {
      fprintf(stderr, "couldn't reopen load\n");
      exit(-1);
    }

  if((stat_file=freopen("/proc/stat", "r", stat_file))==NULL) 
    {
      fprintf(stderr, "couldn't reopen stat\n");
      exit(-1);
    }
   
  for(count=0; count<4; count++) {
    fscanf(loadavd_file, "%f", &loadavg[count]);
    fprintf(stderr, "load[%i]=%f\n", count, loadavg[count]);
  }
  
  fscanf(stat_file, "%s ", dummy);

  for(count=0; count<4; count++) {
    fscanf(stat_file, "%f", &stat[count]);
    jiffies[count]=stat[count]-olde_stat[count];
    fprintf(stderr, "stat[%i]=%i\n", count, jiffies[count]);
    olde_stat[count]=stat[count];
  }

  return 0;  
}

