//-----------------------------------------------------------------------------
// Written by Ch. Tronche (http://tronche.lri.fr:8000/)
// Copyright by the author. This is unmaintained, no-warranty free software.
// Please use freely. It is appreciated (but by no means mandatory) to
// acknowledge the author's contribution. Thank you.
// Started on Thu Jun 26 23:29:03 1997

//
// Xlib tutorial: 2nd program
// Make a window appear on the screen and draw a line inside.
// If you don't understand this program, go to
// http://tronche.lri.fr:8000/gui/x/xlib-tutorial/2nd-program-anatomy.html
//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h> // Every Xlib program must include this
#include <X11/keysym.h>
#include <assert.h>   // I include this to test return values the lazy way
#include <unistd.h>   // So we got the profile for 10 seconds

#include "calibrationDraw.h"
#include "pthread.h"
#include "sample_grabber.h"

#define NIL (0)       // A name for the void pointer

int g_userAbort = 0;
int g_curState = 0;
int g_prevState = 0;
int g_touchEnabled = 0;
int g_IOCTLInProgress = 0;

extern int calibPointsNum;

//-----------------------------------------------------------------------------
Cursor CreateEmptyCursor(Display *display, Window root)
{	
    char    nothing[] = {0};
    XColor  nullcolor;
    Pixmap  src      = XCreateBitmapFromData(display, root, nothing, 1, 1);
    Pixmap  msk      = XCreateBitmapFromData(display, root, nothing, 1, 1);
    Cursor  mycursor = XCreatePixmapCursor(display, src, msk, &nullcolor, &nullcolor, 0, 0);

    XFreePixmap(display, src);
    XFreePixmap(display, msk);

    return mycursor;
}

//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
    
    unsigned long   attrmask;
    KeySym          keysym;
    XComposeStatus  compose;
    char            buf[40];      
    int             bufsize = 40;

    // Linux pthread
    pthread_t       io_worker_thread;
    pthread_attr_t  attr;
    int             status, rc;

	// Open the display
    Display *dpy = XOpenDisplay(NIL);
    int     screen_num = DefaultScreen(dpy);
    Window  root = RootWindow(dpy, screen_num);
    char*   font_name = "*-helvetica-*-24-*";

    XFontStruct*    font_info;
    XSetWindowAttributes    attrs;



    assert(dpy);

    // Get some colors
    int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
    int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));

    attrmask = (CWOverrideRedirect | CWEventMask | CWBackingStore | CWColormap |
                CWBackPixel | CWBackingPixel | CWBorderPixel | CWCursor);

    attrs.override_redirect = True;
    attrs.event_mask        = (KeyPressMask | KeyReleaseMask | ButtonPressMask |
                               ButtonReleaseMask | PointerMotionMask);
    attrs.backing_store     = NotUseful;
    attrs.colormap          = 0;
    attrs.background_pixel  = blackColor;
    attrs.backing_pixel     = blackColor;
    attrs.border_pixel      = whiteColor;
	attrs.cursor            = CreateEmptyCursor(dpy, root);	

    // Create the window
    Window w = XCreateWindow(dpy,
                             root,
                             0,
                             0,
                             DisplayWidth(dpy, screen_num),
                             DisplayHeight(dpy, screen_num),
                             0,
                             CopyFromParent,
                             InputOutput,
                             CopyFromParent,
                             attrmask,
                             &attrs);

    // We want to get MapNotify events
    XSelectInput(dpy, w, StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask);

    // "Map" the window (that is, make it appear on the screen)
    XMapWindow(dpy, w);

    XGrabKeyboard(dpy, w, False, GrabModeAsync, GrabModeAsync, CurrentTime);
    XGrabServer(dpy);

    // Create a "Graphics Context"
    GC gc = XCreateGC(dpy, w, 0, NIL);

    // Tell the GC we draw using the white color
	XSetForeground(dpy, gc, whiteColor);
    XSetInputFocus(dpy, w, RevertToNone, CurrentTime);

	font_info = XLoadQueryFont(dpy, font_name);
    if (font_info)
		XSetFont(dpy, gc, font_info->fid);


	// Wait for the MapNotify event
    for(;;) {
        XEvent e;
        XNextEvent(dpy, &e);
        switch (e.type) {
            case MapNotify:

                SetScreenDimension(dpy,
                                   (Drawable)w,
                                   gc,
                                   DisplayWidth(dpy, screen_num),
                                   DisplayHeight(dpy, screen_num),
                                   font_info);

                g_curState = g_prevState = 0;
                ShowPoint(calibPointsNum, g_curState);
                g_touchEnabled = 1;

                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
                rc = pthread_create(&io_worker_thread, &attr, IOWorkerThread, (void *) NULL);
				if(rc) {
                    fprintf(stderr, "ERROR: return %d from pthread_create()\n",rc);


                    exit(-1);
                }
                pthread_attr_destroy(&attr);
                break;
            case ButtonRelease:
                //printf("ButtonPress state=%d\n", g_curState);


                if(g_curState <= calibPointsNum && g_curState != g_prevState) {
                    ShowPoint(calibPointsNum, g_curState);
                    g_touchEnabled = 1;
                }

                if(g_curState > calibPointsNum) {
                    XUngrabServer(dpy);
                    XUngrabKeyboard(dpy, CurrentTime);
                    XFreeGC(dpy, gc);
                    XCloseDisplay(dpy);


                    /*
                    rc = pthread_join(io_worker_thread, (void **)&status);
                    if(rc)
                        fprintf(stderr, "ERROR: return %d from pthread_join()\n", rc);
                    */
                    exit(0);	
                }
                break;
            case KeyPress:

                XLookupString((XKeyEvent*)&e, buf, bufsize, &keysym, &compose);
                if(keysym == XK_Return && g_IOCTLInProgress == 0) {
                    g_userAbort = 1;
                    XUngrabServer(dpy);
                    XUngrabKeyboard(dpy, CurrentTime);
                    XFreeGC(dpy, gc);
                    XCloseDisplay(dpy);
                    //TODO:	notice the io_worker_thread
                    //	wait till it finishes.
                    rc = pthread_join(io_worker_thread, (void **)&status);
                    if(rc)
						fprintf(stderr, "ERROR: return %d from pthread_join()\n",rc);
                    exit(0);
                }
                break;
            default:
                break;
        }//switch
    }//for

    sleep(3);
}
