/*
 *      touchscreen_gesture.c
 *      Grab touchscreen events until a gesture is drawn on the screen - http://www.sneaked.net      
 *      This source code is inspired by <http://lindi.iki.fi/lindi/openmoko/touchscreen-lock.c>
 *
 *      Copyright (c) 2009 Mauro Gentile a.k.a. sneak <chiudisessione@gmail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */

#include <stdio.h>
#include <time.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>

struct input_event {
    struct timeval time;
    uint16_t type;
    uint16_t code;
    int32_t value;
};

struct v3 {
    int x; int y; int z;
};

#define HISTSIZE 15
#define MAX_X 18
#define DIFF_MIN_MAX 10
#define Error_(x) puts(x)

int main(int argc, char *argv[]) {
    static struct v3 pos;
    struct input_event e;
    FILE *fp;
    int ret, prev_y_zone = 0, prev_x_zone = 0, i;
    int zone_history[HISTSIZE], zone_history_ptr = 0, zone_history_x[HISTSIZE], zone_history_ptr_x = 0;
    
    if (argc != 2){
        Error_("Usage: ./touchscreen_gesture /dev/input/touchscreen0");
        exit(0);
    }

    memset(zone_history_x,0,HISTSIZE);	
    memset(zone_history,0,HISTSIZE);

    fp = fopen(argv[1], "r");
    
    ioctl(fileno(fp), 0x40044590 | FIOASYNC, 1); // EVIOCGRAB

    for (;;) {
        ret = fread(&e, sizeof(e), 1, fp);
  

        if (e.type == 3 && e.code == 0)
            pos.y = e.value;
	if (e.type == 3 && e.code == 1)
            pos.x = e.value;
	if (e.type == 0 && e.code == 0) {
            int y_zone, match, x_zone;
            
            y_zone = pos.y / 50;
	    x_zone = pos.x / 50;
		
	    // printf("y: %d, x: %d \n", y_zone, x_zone);
            if (y_zone != prev_y_zone) {
                prev_y_zone = y_zone;
                zone_history[(zone_history_ptr++) % HISTSIZE] = y_zone;
            }
		
            if (x_zone != prev_x_zone) {
                prev_x_zone = x_zone;
                zone_history_x[(zone_history_ptr_x++) % HISTSIZE] = x_zone;
            }


            match = 1;
            for (i = 0; i < HISTSIZE - 1; i++) {
                if (zone_history[(zone_history_ptr + i) % HISTSIZE] !=
                    zone_history[(zone_history_ptr + i + 1) % HISTSIZE] + 1 && 
		    zone_history_x[(zone_history_ptr_x + i) % HISTSIZE] + 1 !=
                    zone_history_x[(zone_history_ptr_x + i + 1) % HISTSIZE]) {
                    match = 0;
                    break;
                }
            }
		
	    if (match && (getMax(zone_history_x)-getMin(zone_history_x) >= DIFF_MIN_MAX) && isCresc(zone_history_x)) {
	        /* 
	        *  You can modify the following command.
	        */
	        
		execlp("zenity","zenity","--warning","--text=Gesture...",0);
		return 0;
            }
        }
    }
    return 0;
}

int getMin(int c[]){
	int min = c[0];
	int i;

	for (i = 0; i < HISTSIZE; i++){
		if (c[i] < min && c[i] != 0)
				min = c[i];
	}
	return min;
}

int getMax(int c[]){
        int max = c[0];
        int i;

        for (i = 0; i < HISTSIZE; i++){
                if (c[i] > max && c[i] < MAX_X && c[i] != 0)
                                max = c[i];
        }
        return max;
}

int isCresc(int c[]){
	int i, j;
	int min = getMin(c);
	int index;

	for (j = 0; j < HISTSIZE; j++){
		if (!(c[j] - min))
			index = j;			
	}

	for (i = index; i < HISTSIZE - 1; i++){
		if (c[i] > c[i+1])
			return 0;
	}

	return 1;
}


