/*
 *    wmupmon - A dockapp to monitor system uptime
 *    Copyright (C) 2003/4  Justin Spadea <justin@j-z-s.com>
 *
 *    Based on work by Seiichi SATO <ssato@sh.rim.or.jp>
 *    Copyright (C) 2001,2002  Seiichi SATO <ssato@sh.rim.or.jp>
 *    AND by Mark Staggs <me@markstaggs.net>
 *    Copyright (C) 2002  Mark Staggs <me@markstaggs.net>

 *    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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "dockapp.h"
#include "backlight_on.xpm"
#include "backlight_off.xpm"
#include "backlight2_on.xpm"
#include "backlight2_off.xpm"
#include "parts.xpm"

#define SIZE	    58
#define WINDOWED_BG "  \tc #AEAAAE"
#define MAX_HISTORY 16
#define CPUNUM_NONE -1

typedef enum { LIGHTON, LIGHTOFF } light;

Pixmap pixmap;
Pixmap backdrop_on;
Pixmap backdrop_off;
Pixmap parts;
Pixmap mask;
static char	*display_name = "";
static char	*light_color = NULL;	/* back-light color */
static unsigned update_interval = 1;
static light    backlight = LIGHTOFF;
static int      style = 1;				/* 1 = default, 2 = new style */


/* prototypes */
static void update(void);
static void switch_light(void);
static void draw_daydigit(int per);
static void draw_hourdigit(int per);
static void draw_minutedigit(int per);
static void draw_seconddigit(int per);
static void parse_arguments(int argc, char **argv);
static void print_help(char *prog);

int main(int argc, char **argv)
{
   int i, a, aa, b, bb;
   char* real_off_xpm[(style == 2 ? sizeof(backlight2_off_xpm) :
                       sizeof(backlight_off_xpm))];
   char* real_on_xpm[(style == 2 ? sizeof(backlight2_on_xpm) :
                       sizeof(backlight_on_xpm))];
   XEvent event;
   XpmColorSymbol colors[2] = { {"Back0", NULL, 0}, {"Back1", NULL, 0} };
   int ncolor = 0;

   /* Parse CommandLine */
   parse_arguments(argc, argv);
   
   /* setup pixmap to use - this is ugly but it works */
   
   a = sizeof(backlight2_off_xpm);
   aa = sizeof(backlight2_on_xpm);
   b = sizeof(backlight_off_xpm);
   bb = sizeof(backlight_on_xpm);
   if(style == 2){
      for(i=0; i<a; i++)
         real_off_xpm[i] = backlight2_off_xpm[i];
      for(i=0; i<aa; i++)
         real_on_xpm[i] = backlight2_on_xpm[i];
   } else {
      for(i=0; i<b; i++)
         real_off_xpm[i] = backlight_off_xpm[i];
      for(i=0; i<bb; i++)
         real_on_xpm[i] = backlight_on_xpm[i];
   }

   /* Initialize Application */
   dockapp_open_window(display_name, PACKAGE, SIZE, SIZE, argc, argv);
   dockapp_set_eventmask(ButtonPressMask);

   if(light_color)
   {
      colors[0].pixel = dockapp_getcolor(light_color);
      colors[1].pixel = dockapp_blendedcolor(light_color, -24, -24, -24, 1.0);
      ncolor = 2;
   }

   /* change raw xpm data to pixmap */
   if(dockapp_iswindowed)
      real_on_xpm[1] = real_off_xpm[1] = WINDOWED_BG;

   if(!dockapp_xpm2pixmap(real_on_xpm, &backdrop_on, &mask, colors, ncolor))
   {
      fprintf(stderr, "Error initializing backlit background image.\n");
      exit(1);
   }
   if(!dockapp_xpm2pixmap(real_off_xpm, &backdrop_off, NULL, NULL, 0))
   {
      fprintf(stderr, "Error initializing background image.\n");
      exit(1);
   }
   if(!dockapp_xpm2pixmap(parts_xpm, &parts, NULL, colors, ncolor))
   {
      fprintf(stderr, "Error initializing parts image.\n");
      exit(1);
   }

   /* shape window */
   if(!dockapp_iswindowed)
      dockapp_setshape(mask, 0, 0);
   if(mask) XFreePixmap(display, mask);

   /* pixmap : draw area */
   pixmap = dockapp_XCreatePixmap(SIZE, SIZE);

   /* Initialize pixmap */
   if(backlight == LIGHTON){
      dockapp_copyarea(backdrop_on, pixmap, 0, 0, SIZE, SIZE, 0, 0);
   } else {
      dockapp_copyarea(backdrop_off, pixmap, 0, 0, SIZE, SIZE, 0, 0);
   }
   dockapp_set_background(pixmap);
   dockapp_show();

   /* Main loop */
   while(1)
   {
      if (dockapp_nextevent_or_timeout(&event, update_interval * 1000))
      {
         /* Next Event */
         switch(event.type)
         {
            case ButtonPress:
               switch_light();
               break;
            default: /* make gcc happy */
               break;
         }
      }
      else
      {
         /* Time Out */
         update();
      }
   }

   return 0;
}

/* called by timer */
static void update(void)
{
   static light pre_backlight;
   int total_secs = 0, seconds, minutes, hours, days;

   /* get current uptime in seconds */
   total_secs = get_uptime();

   /* parse time into units */
   seconds = total_secs % 60;
   minutes = (total_secs / 60) % 60;
   hours = (total_secs / 3600) % 24;
   days = total_secs / 86400;

   /* all clear */
   if (backlight == LIGHTON){
      dockapp_copyarea(backdrop_on, pixmap, 0, 0, 58, 58, 0, 0);
   } else {
      dockapp_copyarea(backdrop_off, pixmap, 0, 0, 58, 58, 0, 0);
   }

   /* draw digits */
   draw_daydigit(days);
   draw_hourdigit(hours);
   draw_minutedigit(minutes);
   draw_seconddigit(seconds);

   /* show */
   dockapp_copy2window(pixmap);
}

/* called when mouse button pressed */
static void switch_light(void)
{
   int total_secs = 0, seconds, minutes, hours, days;

   switch (backlight)
   {
      case LIGHTOFF:
         backlight = LIGHTON;
         dockapp_copyarea(backdrop_on, pixmap, 0, 0, 58, 58, 0, 0);
         break;
      case LIGHTON:
         backlight = LIGHTOFF;
         dockapp_copyarea(backdrop_off, pixmap, 0, 0, 58, 58, 0, 0);
         break;
   }

   /* get current cpu usage in percent */
   total_secs = get_uptime();

   seconds = total_secs % 60;
   minutes = (total_secs / 60) % 60;
   hours = (total_secs / 3600) % 24;
   days = total_secs / 86400;
   
   /* redraw digit */
   draw_daydigit(days);
   draw_hourdigit(hours);
   draw_minutedigit(minutes);
   draw_seconddigit(seconds);

   /* show */
   dockapp_copy2window(pixmap);
}

static void draw_daydigit(int num)
{
   /* if #days < 100 we only draw 2 digits, else we draw 3 */
   int v100, v10, v1;
   int y=40, x1=0, x2=0, x3=0;

   if (num < 0) num = 0;

   v100 = num / 100;
   v10  = (num - v100 * 100) / 10;
   v1   = (num - v100 * 100 - v10 * 10);

   // no backlight: x = 0 + (digit number * 5)
   // with backlight: x = 50 + (digit number * 5)
   x1 = v100 * 5;
   x2 = v10 * 5;
   x3 = v1 * 5;
   if (backlight == LIGHTON){
      x1 += 50;
      x2 += 50;
      x3 += 50;
   }

   /* draw digits */
   if (num < 100){
      dockapp_copyarea(parts, pixmap, x2, y, 5, 9, 5, 14);
      dockapp_copyarea(parts, pixmap, x3, y, 5, 9, 11, 14);
   } else {
      dockapp_copyarea(parts, pixmap, x1, y, 5, 9, 5, 14);
      dockapp_copyarea(parts, pixmap, x2, y, 5, 9, 11, 14);
      dockapp_copyarea(parts, pixmap, x3, y, 5, 9, 17, 14);
   }
}

static void draw_hourdigit(int num)
{
   int v100, v10, v1;
   int y=40, x1=0, x2=0;

   if (num < 0) num = 0;

   v10 = num / 10;
   v1  = num - (v10 * 10);

   // no backlight: x = 0 + (digit number * 5)
   // with backlight: x = 50 + (digit number * 5)
   x1 = v10 * 5;
   x2 = v1 * 5;
   if (backlight == LIGHTON){
      x1 += 50;
      x2 += 50;
   }

   /* draw digits */
   dockapp_copyarea(parts, pixmap, x1, y, 5, 9, 5, 25);
   dockapp_copyarea(parts, pixmap, x2, y, 5, 9, 11, 25);
}

static void draw_minutedigit(int num)
{
   int v100, v10, v1;
   int y=40, x1=0, x2=0;

   if (num < 0) num = 0;

   v10 = num / 10;
   v1  = num - (v10 * 10);

   // no backlight: x = 0 + (digit number * 5)
   // with backlight: x = 50 + (digit number * 5)
   x1 = v10 * 5;
   x2 = v1 * 5;
   if (backlight == LIGHTON){
      x1 += 50;
      x2 += 50;
   }

   /* draw digits */
   dockapp_copyarea(parts, pixmap, x1, y, 5, 9, 5, 36);
   dockapp_copyarea(parts, pixmap, x2, y, 5, 9, 11, 36);
}

static void draw_seconddigit(int num)
{
   int v100, v10, v1;
   int y=40, x1=0, x2=0;

   if (num < 0) num = 0;

   v10 = num / 10;
   v1  = num - (v10 * 10);

   // no backlight: x = 0 + (digit number * 5)
   // with backlight: x = 50 + (digit number * 5)
   x1 = v10 * 5;
   x2 = v1 * 5;
   if (backlight == LIGHTON){
      x1 += 50;
      x2 += 50;
   }

   /* draw digits */
   dockapp_copyarea(parts, pixmap, x1, y, 5, 9, 5, 47);
   dockapp_copyarea(parts, pixmap, x2, y, 5, 9, 11, 47);
}

static void parse_arguments(int argc, char **argv)
{
   int i;
   int integer;
   for (i = 1; i < argc; i++) 
   {
      if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h"))
         print_help(argv[0]), exit(0);
      else if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v"))
         printf("%s version %s\n", PACKAGE, VERSION), exit(0);
      else if (!strcmp(argv[i], "--display") || !strcmp(argv[i], "-d")) 
      {
         display_name = argv[i + 1];
         i++;
      }
      else if (!strcmp(argv[i], "--backlight") || !strcmp(argv[i], "-bl"))
         backlight = LIGHTON;
      else if (!strcmp(argv[i], "--light-color") || !strcmp(argv[i], "-lc")) 
      {
         light_color = argv[i + 1];
         i++;
      }
	  else if (!strcmp(argv[i], "--style") || !strcmp(argv[i], "-s")) 
      {
         if (argc == i + 1)
             fprintf(stderr, "%s: error parsing argument for option %s\n",
                    argv[0], argv[i]), exit(1);
         if (sscanf(argv[i + 1], "%i", &integer) != 1)
             fprintf(stderr, "%s: error parsing argument for option %s\n",
                     argv[0], argv[i]), exit(1);
         if (integer != 1 && integer != 2)
             fprintf(stderr, "%s: argument %s must be 1 or 2\n",
                     argv[0], argv[i]), exit(1);
         style = integer;
         i++;
      }
      else if (!strcmp(argv[i], "--interval") || !strcmp(argv[i], "-i")) 
      {
         if (argc == i + 1)
            fprintf(stderr, "%s: error parsing argument for option %s\n",
                    argv[0], argv[i]), exit(1);
         if (sscanf(argv[i + 1], "%i", &integer) != 1)
             fprintf(stderr, "%s: error parsing argument for option %s\n",
                     argv[0], argv[i]), exit(1);
         if (integer < 1)
             fprintf(stderr, "%s: argument %s must be >=1\n",
                     argv[0], argv[i]), exit(1);
         update_interval = integer;
         i++;
      }
      else if (!strcmp(argv[i], "--windowed") || !strcmp(argv[i], "-w"))
         dockapp_iswindowed = True;
      else if (!strcmp(argv[i], "--broken-wm") || !strcmp(argv[i], "-bw"))
         dockapp_isbrokenwm = True;
      else
      {
         fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[i]);
         print_help(argv[0]), exit(1);
      }
   }
}

static void print_help(char *prog)
{
   printf("Usage : %s [OPTIONS]\n", prog);
   printf("wmupmon - uptime monitor dockapp\n");
   printf("  -d,  --display <string>        display to use\n");
   printf("  -bl, --backlight               turn on back-light\n");
   printf("  -lc, --light-color <string>    back-light color(rgb:6E/C6/3B is default)\n");
   printf("  -s,  --style <1 or 2>          display style (1 is default)\n");
   printf("  -i,  --interval <number>       number of secs between updates (1 is default)\n");
   printf("  -h,  --help                    show this help text and exit\n");
   printf("  -v,  --version                 show program version and exit\n");
   printf("  -w,  --windowed                run the application in windowed mode\n");
   printf("  -bw, --broken-wm               activate broken window manager fix\n");
}


syntax highlighted by Code2HTML, v. 0.9.1