/* Example 4 */
#include <stdio.h>
#include "EZ.h"

static void  clean_exit(); 
static void  button_callback();
static void eventHandler();
static void  randomize();

static EZ_Widget *toplevel, *buttons[4][4];
static int        width=39, height=33;
static int        emptyx = 3, emptyy = 3;
static int        hpad = 2;

main(int ac, char **av)
{
  int        i,j, k;
  char       str[4], *fname;
  EZ_Widget  *frame, *label, *tmp, *tmp1;
  Pixmap     pixmap;
  int        pw, ph, m,n;

  i = 1; fname = NULL;
  while(i < ac) 
    {
      if(!strcmp(av[i], "-f") && i+1 < ac) fname = av[i+1];
      i++;
    }
  if(fname == NULL ) fprintf(stderr, "Usage %s -f image_file\n",av[0]);
  EZ_Initialize(ac,av,1);
  EZ_SetKbdHighlightColor("red");
  toplevel = EZ_CreateFrame(NULL,NULL);
  EZ_ConfigureWidget(toplevel, EZ_STACKING, EZ_VERTICAL, 0);

  label = EZ_CreateLabel(toplevel, "The 15 Puzzle");
  EZ_ConfigureWidget(label, EZ_FOREGROUND, "blue", 
         EZ_FONT_NAME, "-Adobe-Times-Bold-R-Normal--*-180-*-*-*-*-*-*", 0);

  frame = EZ_CreateFrame(toplevel, NULL); 
  EZ_ConfigureWidget(frame, EZ_PADX,0, EZ_PADY,0,
                     EZ_BORDER_TYPE,EZ_BORDER_SUNKEN,
                     EZ_BORDER_WIDTH, 2, 
                     EZ_WIDTH, 0, EZ_HEIGHT, 0, 0);

  tmp = EZ_CreateFrame(toplevel, NULL);
  tmp1 = EZ_CreateButton(tmp, "Quit",0);
  EZ_ConfigureWidget(tmp1, EZ_CALLBACK, clean_exit, NULL, 0);
  tmp1 = EZ_CreateButton(tmp, "Scramble",0);
  EZ_ConfigureWidget(tmp1, EZ_CALLBACK, randomize, NULL, 0);

  if(fname && EZ_CreateXPixmapFromImageFile(fname,&pw, &ph, &pixmap))
    {
      width = pw/4 + 2*hpad; 
      height = ph/4 + 2*hpad;
    }
  else  pixmap = (Pixmap)NULL;

  for(i = 0; i < 4; i++)  
    for(j = 0; j < 4; j++)
      {
          {
            k = 4 * i + j;
	    if(i +j != 6)
	      {
		sprintf(str,"%d",k+1);
		tmp = buttons[i][j] = EZ_CreateButton(frame,str,-1);
		EZ_SetWidgetIntData(tmp, k); 
		EZ_ConfigureWidget(tmp, 
				   EZ_X, 2 + j * width,
				   EZ_Y, 2 + i * height,
				   EZ_BORDER_WIDTH,1,
				   EZ_PROPAGATE, 0,
				   EZ_WIDTH, width, EZ_HEIGHT, height, 
				   EZ_CALLBACK, button_callback, NULL, 
				   EZ_EVENT_HANDLER, eventHandler, NULL, 
				   0);
		if(pixmap)
		  EZ_ConfigureWidget(tmp, 
				     EZ_X_PIXMAP, pixmap, j*(width-2*hpad),i*(height-2*hpad), 
				     width-2*hpad, height-2*hpad,  0);
	      }
	  }
      }
  if(pixmap) EZ_FreeXPixmap(pixmap);

  srand(getpid()); 
  EZ_DisplayWidget(toplevel); 
  EZ_EventMainLoop();
}

static void button_callback(EZ_Widget *widget, void *data)
{
  int tmp, x, y;
  
  tmp = EZ_GetWidgetIntData(widget);
  x = tmp >> 2;
  y = tmp & 0x3;

  if(abs(emptyx - x) + abs(emptyy - y) == 1) /* I'm next to the empty square */
    {                                        /*   swap with the empty square */
      int tx = emptyx, ty = emptyy;
      emptyx = x; emptyy = y;                       /* the new empty square */
      EZ_SetWidgetIntData(widget, 4 * tx + ty);     /* and my new location  */
      EZ_SetWidgetPosition(widget, 2 + ty * width, 2 + tx * height);
    }
}

static void randomize(EZ_Widget *widget, void *data)
{                                          /* just make a few random moves */
  int i, x, y;
  for(i = 0; i < 500; i++)
    {
      x = (rand()>> 5) % 4;
      y = (rand()>> 5) % 4;
      if((x + y != 6)) button_callback(buttons[x][y], NULL);
    }
}

static void  clean_exit(EZ_Widget *widget, void *data)
{
  EZ_DestroyWidget(toplevel);  /* destroy all widgets */
  EZ_Shutdown();               /* clean up the heap   */
  exit(0);
}

void eventHandler(EZ_Widget *widget, void *data, int etype, XEvent *event)
{
  if(etype == EZ_KEY_PRESS)
    {
      int dx = 0, dy= 0;
      switch(EZ_PressedKey)
	{
	case EZ_UP_KEY:    dx =  -1;  break;
	case EZ_DOWN_KEY:  dx = 1; break;
	case EZ_LEFT_KEY:  dy = -1; break;
	case EZ_RIGHT_KEY: dy = 1;  break;
	default: break;
	}
      if(dx || dy )
	{
	  EZ_Widget *wgt;
	  int i,j, tmp;
	  int xx = emptyx - dx;
	  int yy = emptyy - dy;
	  if(xx < 0 || xx >= 4 || yy < 0 || yy >= 4) return;
	  tmp = 4 * xx + yy;
	  for(i = 0; i < 4; i++) for(j = 0; j < 4; j++) 
	    {
	      if(i + j == 6) break;
	      if(EZ_GetWidgetIntData(buttons[i][j]) == tmp)
		{
		  int values[2];
		  values[0] = ' '; values[1] = 0;
		  wgt = buttons[i][j];
		  button_callback(wgt, NULL);
		  EZ_SetFocusTo(wgt);
		}
	    }
	}
    }
}
