/* symrad.c - A radiator simulation game. */

#include <stdio.h>
#include <stdlib.h>

#include <X11/Xlib.h>

#include "symrad.h"


/* ---------- Local function declarations ---------- */
int init(symrad_type);
void go(symrad_type);
void do_Expose(symrad_type, XEvent *);
void do_Enter(symrad_type, XEvent *);
void do_Leave(symrad_type, XEvent *);
void do_Press(symrad_type, XEvent *);
void do_Release(symrad_type, XEvent *);

/* ---------------------------------------------------------------------- */
void do_Expose(symrad_type symrad, XEvent *ev)
{
  if (ev->xexpose.window == symrad->win) {
    /* Symrad expose stuff here */
    XCopyPlane(symrad->dpy, symrad->bigpix, symrad->win, symrad->gc,
	       0, 0, BIGPIX_WIDTH, BIGPIX_HEIGHT,
	       BIGPIX_POS_X, BIGPIX_POS_Y,
	       0);

    /* Now paint the little guy */
    XCopyPlane(symrad->dpy, 
	       symrad->littlepix[symrad->position % NUM_PIXES],
	       symrad->win, symrad->gc,
	       0, 0, LITTLEPIX_WIDTH, LITTLEPIX_HEIGHT,
	       LITTLEPIX_POS_X, LITTLEPIX_POS_Y,
	       0);
  }
  else {
    if (ev->xexpose.window == symrad->butt1->win) {
      button_Expose(symrad->butt1, ev);
    }
    else if (ev->xexpose.window == symrad->butt2->win) {
      button_Expose(symrad->butt2, ev);
    }
    else {
      fprintf(stderr, "Unknown window getting Expose event.\n");
    }
  }
}

/* ---------------------------------------------------------------------- */
void do_Enter(symrad_type symrad, XEvent *ev)
{
  if (symrad->butt1->win == ev->xcrossing.window) {
    button_Enter(symrad->butt1, ev);
  }
  else if (symrad->butt2->win == ev->xcrossing.window) {
    button_Enter(symrad->butt2, ev);
  }
  else {
    fprintf(stderr, "Unknown window getting Enter event.\n");
  }
}

/* ---------------------------------------------------------------------- */
void do_Leave(symrad_type symrad, XEvent *ev)
{
  if (symrad->butt1->win == ev->xcrossing.window) {
    button_Leave(symrad->butt1, ev);
  }
  else if (symrad->butt2->win == ev->xcrossing.window) {
    button_Leave(symrad->butt2, ev);
  }
  else {
    fprintf(stderr, "Unknown window getting Leave event.\n");
  }
}

/* ---------------------------------------------------------------------- */
void do_Press(symrad_type symrad, XEvent *ev)
{
  if (symrad->butt1->win == ev->xbutton.window) {
    button_Press(symrad->butt1, ev);
  }
  else if (symrad->butt2->win == ev->xbutton.window) {
    button_Press(symrad->butt2, ev);
  }
  else {
    fprintf(stderr, "Unknown window getting Press event. \n");
  }
}

/* ---------------------------------------------------------------------- */
void do_Release(symrad_type symrad, XEvent *ev)
{
  if (symrad->butt1->win == ev->xbutton.window) {
    button_Release(symrad->butt1, ev);
  }
  else if (symrad->butt2->win == ev->xbutton.window) {
    button_Release(symrad->butt2, ev);
  }
  else {
    fprintf(stderr, "Unknown window getting Release event. \n");
  }
}

/* ---------------------------------------------------------------------- */
void go(symrad_type symrad)
{
  XEvent ev;

  /* Standard stuff */
  while (1) {
    XNextEvent(symrad->dpy, &ev);
    switch(ev.type) {
    case MappingNotify:
      XRefreshKeyboardMapping((XMappingEvent *)&ev);
      break;
      
    case Expose:
      do_Expose(symrad, &ev);
      break;

    case EnterNotify:
      do_Enter(symrad, &ev);
      break;

    case LeaveNotify:
      do_Leave(symrad, &ev);
      break;

    case ButtonPress:
      do_Press(symrad, &ev);
      break;

    case ButtonRelease:
      do_Release(symrad, &ev);
      break;

    default:
      fprintf("Unknown Event Type (%d)\n", ev.type);
      break;
    }
  }
}

/* ---------------------------------------------------------------------- */
int init(symrad_type symrad)
{
  int ret;

  /* Start out by opening the window */
  symrad->extent.x = INIT_X;
  symrad->extent.y = INIT_Y;
  symrad->extent.width = INIT_WIDTH;
  symrad->extent.height = INIT_HEIGHT;
  symrad->win = XCreateSimpleWindow(symrad->dpy,
				    DefaultRootWindow(symrad->dpy),
				    symrad->extent.x,
				    symrad->extent.y,
				    symrad->extent.width,
				    symrad->extent.height,
				    0, 0, 0);

  if (!symrad->win) {
    ret = CANT_OPEN_WINDOW;
    goto err0;
  }

  /* Now create the buttons */
  symrad->butt1 = 
    button_Create(symrad->dpy, symrad->win, 
		  "Lefty Loosy",
		  LEFT_X, LEFT_Y, LEFT_WIDTH, LEFT_HEIGHT);

  if (!symrad->butt1) {
    ret = CANT_OPEN_LEFTBUTT;
    goto err1;
  }
  
  symrad->butt2 = 
    button_Create(symrad->dpy, symrad->win, 
		  "Righty Tighty", 
		  RIGHT_X, RIGHT_Y, RIGHT_WIDTH, RIGHT_HEIGHT);

  if (!symrad->butt2) {
    ret = CANT_OPEN_RIGHTBUTT;
    goto err2;
  }
				    
  /* Read in the bitmaps */
  {
    char buf[NAMELEN];
    unsigned int width, height;
    int x_hot, y_hot;

    sprintf(buf, "%sbig.pm", PIXNAME);
    if (XReadBitmapFile(symrad->dpy, DefaultScreen(symrad->dpy),
			buf, &width, &height,
			&symrad->bigpix, &x_hot, &y_hot) != BitmapSuccess) {
      ret = BAD_PIXMAPS;
      goto err3;
    }
			
    /* Get the little ones */
    for (i = 0; i < NUM_PIXES; i++) {
      sprintf(buf, "%s%d.pm", PIXNAME, i);
      if (XReadBitmapFile(symrad->dpy, DefaultScreen(symrad->dpy),
	 		  buf, &width, &height,
			  &symrad->littlepix[i], 
			  &x_hot, &y_hot) != BitmapSuccess) {
	ret = BAD_PIXMAPS;
	goto err5;
      }
    }
  }

  symrad->desired = /* Set this randomly */;
  symrad->position = /* Set this randomly */;

  /* Map it AFTER the buttons are created */
  XMapRaised(symrad->win);
  
  /* Now solicit events */
  XSelectInput(symrad->dpy, symrad->win, ExposureMask);

  return 0;

 err5:
  /* Okay, a little bug here.  If this fails, it doesn't kill all of the */
  /* pixmaps like it should.  Fix this sometime in the future when you */
  /* are bored and have absolutely nothing else to do.  It should take */
  /* about two minutes. */
 err4:
  XFreePixmap(symrad->bigpix);
 err3:
  button_Destroy(symrad->butt2);
 err2:
  button_Destroy(symrad->butt1);
 err1:
  XDestroyWindow(symrad->win);
 err0:
  return ret;
}

/* ---------------------------------------------------------------------- */
int main(int argc, char *argv[])
{
  int i;
  char *dpyname = NULL;
  symrad_struct symrad;

  /* Process arguments */
  i = 1;
  while (i < argc) {
    switch (argv[i][0]) {
    case '-':
      if (!strcmp("display", argv[i] + 1)) {
	dpyname = argv[++i];
      }
      break;

    default:
      break;
    }
    i++;
  }

  /* Open the display */
  if ((symrad.dpy = XOpenDisplay(dpyname)) == NULL) {
    fprintf(stderr, "Can't open display connection to %s.\n", dpyname);
    exit(BAD_DPY);
  }

  if ((i = init(&symrad)) != 0) {
    fprintf(stderr, "Can't initialize radiator.  Error code: %d.\n", i);
    XCloseDisplay(symrad.dpy);
    exit(i);
  }

  go(&symrad);

  return 0;
}
