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

#include <unistd.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>

#define TRUE (1==1)
#define FALSE (1==0)

#define STARTX 997
#define STARTY 375
#define WIDTH 42
#define HEIGHT 42
#define COLUMNS 8
#define ROWS 9

#define ORANGE 0xffd341
#define VERT 0xa8bf36
#define BLANC 0xf2f2f2
#define ROSE 0xe01271
#define VIOLET 0xa842b0
#define BLEU 0x5ba4dd

Display *display;
Window rootwindow;

void mouseMove(int x,int y) {
  XWarpPointer(
    display,
    None,
    rootwindow,
    0,0,
    0,0,
    x,y
  );

  XFlush(display);
}

void mouseClick(int button) {
  XEvent event;
  
  memset(&event,0x00,sizeof(event));
  
  event.type               =ButtonPress;
  event.xbutton.button     =button;
  event.xbutton.same_screen=True;
  
  XQueryPointer(
    display,
    /*RootWindow(display,DefaultScreen(display)),*/
    rootwindow,
    &event.xbutton.root,
    &event.xbutton.window,
    &event.xbutton.x_root,
    &event.xbutton.y_root,
    &event.xbutton.x,
    &event.xbutton.y,
    &event.xbutton.state
  );
  
  event.xbutton.subwindow=event.xbutton.window;
  
  while(event.xbutton.subwindow) {
    event.xbutton.window=event.xbutton.subwindow;
    
    XQueryPointer(
      display,
      event.xbutton.window,
      &event.xbutton.root,
      &event.xbutton.subwindow,
      &event.xbutton.x_root,
      &event.xbutton.y_root,
      &event.xbutton.x,
      &event.xbutton.y,
      &event.xbutton.state
    );
  }

  if(XSendEvent(display,PointerWindow,True,0xfff,&event)==0) {
    fprintf(stderr, "Erreur à la génération de l’événement !!!\n");
  }
  
  XFlush(display);

  usleep(60000);
  
  event.type         =ButtonRelease;
  event.xbutton.state=0x100;
  
  if(XSendEvent(display,PointerWindow,True,0xfff,&event)==0) {
    fprintf(stderr, "Erreur à la génération de l’événement !!!\n");
  }
  XFlush(display);
}

unsigned long getPixel(int x,int y) {
  XImage *image;

  image=XGetImage(
    display,
    rootwindow,
    x,y,
    1,1,
    AllPlanes,
    ZPixmap
  );

  return XGetPixel(image,0,0);
}

int fillGrid(char grid[ROWS][COLUMNS]) {
  int i,j,cx=0;

  for(j=0;j<ROWS;j++) {
    for(i=0;i<COLUMNS;i++) {
      switch(getPixel(STARTX+i*WIDTH,STARTY+j*HEIGHT)) {
        case ORANGE: grid[j][i]='o'; break;
        case VERT  : grid[j][i]='g'; break;
        case BLANC : grid[j][i]='w'; break;
        case ROSE  : grid[j][i]='r'; break;
        case VIOLET: grid[j][i]='v'; break;
        case BLEU  : grid[j][i]='b'; break;
        default    : grid[j][i]='x'; cx++;
      }
    }
  }

  if(cx==(ROWS*COLUMNS)) {
    return FALSE;
  } else {
    return TRUE;
  }
}

void printGrid(char grid[ROWS][COLUMNS]) {
  int i,j;
  for(j=0;j<ROWS;j++) {
    for(i=0;i<COLUMNS;i++) {
      printf("%c",grid[j][i]);
    }
    printf("\n");
  }
}

int searchTwins(char grid[ROWS][COLUMNS],int *x,int *y) {
  int i,j,c;
  char couleurs[]="ogwrvb";

  for(c=0;c<6;c++) {
    /* Horizontal search */
    for(j=0;j<ROWS;j++) {
      for(i=0;i<COLUMNS-1;i++) {
        if(grid[j][i]!=couleurs[c]) continue;
        if(grid[j][i]==grid[j][i+1]) {
          *x=i; *y=j;
          return TRUE;
        }
      }
    }

    /* Vertical search */
    for(j=0;j<ROWS-1;j++) {
      for(i=0;i<COLUMNS;i++) {
        if(grid[j][i]!=couleurs[c]) continue;
        if(grid[j][i]==grid[j+1][i]) {
          *x=i; *y=j;
          return TRUE;
        }
      }
    }
  }

  return FALSE;
}

int main(int argc,char **argv) {
  char grid[ROWS][COLUMNS];
  int i,j;
  int x,y;

  display=XOpenDisplay(NULL);
  rootwindow=RootWindow(display,DefaultScreen(display));

  i=-1;
  j=-1;

  while(fillGrid(grid)) {
    if(searchTwins(grid,&i,&j)) {
      printf("[%d,%d]\n",i,j);
      x=STARTX+i*WIDTH+WIDTH/2;
      y=STARTY+j*HEIGHT;
      mouseMove(x,y);
      usleep(20000);
      mouseClick(1);
    }
    usleep(40000);
  }

  XCloseDisplay(display);
}

