#include <stdio.h>

#include "header.h"
#include "Win.h"
#include "Timer.h"

Timer timer(20);

Win::Win(int width, int height, char *title)
{
     int depth;

     if( (d = XOpenDisplay(NULL)) == NULL ) {
	  fprintf(stderr, "Cannot open display\n");
	  exit(1);
     }

     screen = DefaultScreen(d);
     depth = DefaultDepth(d, screen);
     cmap = DefaultColormap(d, screen);

     w = XCreateSimpleWindow(d, RootWindow(d, screen), 5, 5,
			     width, height, 5, WHITE, WHITE);
     XSelectInput(d, w, ButtonPressMask| ExposureMask);
     XSetWindowColormap(d, w, cmap);

     /* Graphics context */
     gc = XCreateGC(d, w, 0, NULL);
     XSetFillStyle(d, gc, FillTiled);
     /* Load font */
     if( (font = (XLoadQueryFont(d, FONT_NAME))) == NULL ) {
	  fprintf(stderr, "Error loading font: %s\n", FONT_NAME);
	  exit(1);
     }

     set_size(title, width, height);
     XMapWindow(d, w);
     XFlush(d);

     /* Double buffer */
     buf = XCreatePixmap(d, w, width, height, depth);
     clear_area(buf, 0, 0, width, height, WHITE);

     /* Wiat for expose */
     XEvent event;
     for( ; ; ) {
	  if( XPending(d) ) {
	       XNextEvent(d, &event);
	       switch(event.type) {
	       case GraphicsExpose:
	       case Expose:
		    return; /* Got expose */
	       default:
		    break;
	       }
	  } else {
	       timer.delay();
	  }
     }

}


void Win::set_size(char *title, int new_w, int new_h)
{
     XSizeHints size_hints;

     width = new_w;
     height = new_h;

     /* Set window to win_w * win_h (not resizable) */
     size_hints.flags = PSize | PMinSize | PMaxSize;
     size_hints.min_width = width;
     size_hints.max_width = width;
     size_hints.min_height = height;
     size_hints.max_height = height;
     
     XSetStandardProperties(d, w, title, title, None, 0, 0, &size_hints);
     XResizeWindow(d, w, width, height);
     
}


/* Returns 1 & sets point to X & Y pos of a button click if there is a
   click in the Event queue */
int Win::button_click(Point *point)
{
     XEvent event;

     while( XPending(d) ) {
		  XNextEvent(d, &event);
		  switch(event.type) {
		  case GraphicsExpose:
		  case Expose:
		       update();
		       break;
		  case ButtonPress:
		       point->x = event.xbutton.x;
		       point->y = event.xbutton.y;
	    	   return 1;
		  default:
			   //Unknown event...
				break;
		  }
     }

	 return 0;

}


void Win::update(void)
{

     //printf("update\n");
     blit(buf, w, 0, 0, width, height);
     XFlush(d);

}


void Win::blit(Drawable src, Drawable dest, int x, int y, int w, int h)
{
  //  static int o_w, o_h;
  //XGCValues xgcv;
  
  // if( w != o_w || h != o_h ) {
  //xgcv.ts_x_origin = x;
  //xgcv.ts_y_origin = y;
  //xgcv.clip_x_origin = x;
  //xgcv.clip_y_origin = y;
  //XChangeGC(d, gc, GCClipXOrigin | GCClipYOrigin | GCTileStipXOrigin
  //      | GCTileStipYOrigin, &xgcv);
    
  //o_w = w;
  //o_h = h;
  //}

  XSetFillStyle(d, gc, FillTiled);
  XSetTile(d, gc, src);
  XFillRectangle(d, dest, gc, x, y, w, h);

}


/* Clears an area of a DRAWABLE. Not to be confused with XClearArea, which
   clears a window */
void Win::clear_area(Drawable drwbl, int x, int y, int w, int h, int c)
{

     XSetFillStyle(d, gc, FillSolid);
     XSetForeground(d, gc, c? WhitePixel(d, screen) : BlackPixel(d, screen));
     XFillRectangle(d, drwbl, gc, x, y, w, h);
  
}


void Win::print(char *msg, int x,int y, int c)
{

     y += font->ascent + font->descent;
     
     XSetFillStyle(d, gc, FillSolid);
     XSetForeground(d, gc, c? WhitePixel(d, screen) : BlackPixel(d, screen));
     XSetFont(d, gc, font->fid);
     XDrawString(d, buf, gc, x, y, msg, strlen(msg));
  
}


void Win::draw_line(Drawable dest, int x, int y, int dx, int dy, int w, int c)
{

     XSetFillStyle(d, gc, FillSolid);
     XSetForeground(d, gc, c? WhitePixel(d, screen) : BlackPixel(d, screen));
     XSetLineAttributes(d, gc, w, LineSolid, CapNotLast, JoinMiter);
     XDrawLine(d, dest, gc, x, y, dx, dy);

}
