#include <xsimple.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>

#define RND ((double)rand() / RAND_MAX)

#define WIN_X 110
#define WIN_Y 75
#define WIN_W 800
#define WIN_H 600

#define HZ 30

#define NBALLS 5

typedef struct {
   int x, y;
   int oldx, oldy;
   int dx, dy;
   int color;
} BALL;

BALL ball[NBALLS] = {
   {300, 100, -1, -1, 10, -5, 58},
   {100, 300, -1, -1, -5, -10, 59},
   {130, 200, -1, -1, -10, 10, 60},
   {350, 370, -1, -1, 10, 5, 61},
   {600, 350, -1, -1, -5, 10, 62}
};


static int itstime(struct timeval *t)
{
   struct timeval now;
   double s1, s2;

   gettimeofday(&now, NULL);
   s1 = (double)t->tv_sec + (double)t->tv_usec / 1000000;
   s2 = (double)now.tv_sec + (double)now.tv_usec / 1000000;
   if (s2 - s1 >= 1./HZ) {
       *t = now;
       return 1;
   }
   return 0;
}

static void do_balls(void)
{
   int i;

   for (i = 0; i < NBALLS; i++) {
       if (ball[i].oldx != -1)
           fillellipse(ball[i].oldx, ball[i].oldy, 50, 50, BLACK);
   }

   for (i = 0; i < NBALLS; i++)
       fillellipse(ball[i].x, ball[i].y, 50, 50,
               xv.egacolor[ball[i].color]);

   update(0, 0, 0, 0);

   for (i = 0; i < NBALLS; i++) {
       ball[i].oldx = ball[i].x; ball[i].oldy = ball[i].y;

       ball[i].x += ball[i].dx; ball[i].y += ball[i].dy;
       if (ball[i].x == WIN_W - 50 || ball[i].x == 0)
           ball[i].dx = -ball[i].dx;
       if (ball[i].y == WIN_H - 50 || ball[i].y == 0)
           ball[i].dy = -ball[i].dy;
   }
}

int main(int argc, char **argv)
{
   struct timeval t;

   srand(time(NULL));

   xinit("balls", "Balls", "Bouncing Balls", WIN_X, WIN_Y, WIN_W, WIN_H, 0,
           "black", "black", 0);

   gettimeofday(&t, NULL);

   cls(BLACK);

   for (;;) {
       XEvent e;

       if (itstime(&t))
           do_balls();

       while (getevent(&e)) {
           switch (e.type) {
               case KeyPress:
                   switch (XLookupKeysym((XKeyEvent *)&e, 0)) {
                       int i;
                       case XK_Down:
                           for (i = 0; i < NBALLS; i++)
                               ball[i].color = (int)(1 + RND * 15);
                           break;
                       case XK_q:
                           exit(0);
                   }
                   break;
           }
       }
   }
}