  /*
  * Copyright (C) 2009 Intel Corp.
  * Author: Weian Chen <weian.chen@intel.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This library 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
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */



#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include "gesture_recog.h"

stroke *stroke_new (int n)
{
    if (n < 10)
        n = 10;
    stroke *s = malloc (sizeof (stroke));
    s->p = malloc (n * sizeof (point));
    s->num_p = 0;
    s->max_num_p = n;
    s->ex_angle = 0.0; // need reasonable init value
    s->var_angle = 0.0; // need reasonable init value 
    s->ols_a = s->ols_b = s->ols_r = 0.0;
    return s;
}

void stroke_del (stroke *s)
{
    if (s->p)
        free (s->p);
    if (s)
        free (s);
}
void add_point (stroke *s, point p)
{
    s->p[s->num_p].x = p.x;
    s->p[s->num_p].y = p.y;
    s->num_p ++;    
}

void add_point_list (stroke *s, point *p, int n)
{
    int index;
    for (index = 0; index < n; index ++)
      {
        add_point (s, p[index]);
      }
}

void add_point_glist (stroke *s, GSList *list)
{
     GSList *it = NULL;
     coor *c;
     point p;

     for (it = list; it; it = it->next) 
       {
         c = (coor *)it->data;
         p.x = c->x;
         p.y = c->y;
         add_point (s, p);
       }
}


void compute_angle (stroke *s)
{
    int n = s->num_p - 1;
    int index;

    if (n < P_NUM_THRD)
        return;

    for (index = 0; index < n; index ++)
      {
        s->p[index].angle = atan2 ((float) (s->p[index + 1].y - s->p[index].y), (float) (s->p[index + 1].x - s->p[index].x));
        //engine_debug ("y = %d, x = %d\n", (s->p[index + 1].y - s->p[index].y), (s->p[index + 1].x - s->p[index].x));
        //engine_debug ("%f\n", s->p[index].angle);
      }
}

void compute_ex_var (stroke *s)
{
    double sum_ex = 0;
    double sum_var = 0;
    int i;
    int n = s->num_p - 1;
    for (i = 0; i < n; i++) 
        sum_ex += s->p[i].angle;

    s->ex_angle = sum_ex / n;

    for (i = 0; i < n; i ++)
      { 
        sum_var += (s->ex_angle - s->p[i].angle) * (s->ex_angle - s->p[i].angle);
        //engine_debug ("sum_var = %04f\n", sum_var);
      }
    s->var_angle = sum_var / n;
}

// Ordinary Least Square
void compute_ols (stroke *s)
{
    int i;
    int n = s->num_p;
    float dx, dy;
    double sum_x = 0;
    double sum_y = 0;
    double sum_xy = 0;
    double sum_xx = 0;
    double sum_yy = 0;
    double ex,ey;
    double var_x = 0.0;
    double var_y = 0.0;
    double d_sum_x = 0;
    double d_sum_y = 0;
    double dd_sum_x = 0;
    double dd_sum_y = 0;
    double dd_sum_xy = 0;
    double delta = 0;
    double delta_sum = 0;
    double s_s = 0.0;
    double lxx, lyy, lxy;
    //double a,b,r;

    for (i = 0; i < n; i++)
      {
        sum_x += s->p[i].x;
        sum_y += s->p[i].y;
        sum_xy += (s->p[i].x * s->p[i].y);
        sum_xx += (s->p[i].x * s->p[i].x);
        sum_yy += (s->p[i].y * s->p[i].y);
      }
    
    //engine_debug ("sum_x = %ld, sum_y = %ld, sum_xy = %ld, sum_xx = %ld, sum_yy = %ld\n", sum_x, sum_y, sum_xy, sum_xx, sum_yy);
    ex = sum_x / n;
    ey = sum_y / n;

    for (i = 0; i < n; i++)
      {
        var_x += (ex - s->p[i].x) * (ex - s->p[i].x);
        var_y += (ey - s->p[i].y) * (ey - s->p[i].y);
      }

    var_x /= n;
    var_y /= n;

    engine_debug ("var_x = %f, var_y = %f\n", var_x, var_y);

#if 1    
    // It is possible that both var_x and var_y is small than 4, we need to detect which one smaller
    if ((var_x < 2) && (var_x < var_y)){
        s->ols_r = 0.99;
	s->ols_a = 999;
        s->ols_b = ex;
	s->ols_angle = M_PI / 2;
#if 0
	if (s->p[s->num_p - 1].y - s->p[0].y > 0){
            s->ols_angle = M_PI / 2;
            s->ols_a = 999;
	}
        else {
            s->ols_angle = - (M_PI / 2);
            s->ols_a = -999;
	}
#endif
        engine_debug ("ols para is: a = %f, b = %f, r = %f, angle = %f, sin = %f\n",
                    s->ols_a, s->ols_b, s->ols_r, s->ols_angle, sin (s->ols_angle));
        return;
    }

    if ((var_y < 2) && (var_y < var_x)){
        s->ols_r = 0.99;
	s->ols_a = 0.001;
	s->ols_b = ey;
	s->ols_angle = 0.001;
#if 0
        if (s->p[s->num_p - 1].x - s->p[0].x > 0){       
            s->ols_angle = 0.001;
            s->ols_a = 0.001;
        }
        else {
            s->ols_angle = M_PI - 0.001;
            s->ols_a = -0.001;
        }
#endif

        engine_debug ("ols para is: a = %f, b = %f, r = %f, angle = %f, sin = %f\n",
                     s->ols_a, s->ols_b, s->ols_r, s->ols_angle, sin (s->ols_angle));
        return;
    }
#endif

    lxy = (double)sum_xy - (double)(sum_x * sum_y / n);
    lxx = (double)sum_xx - (double)(sum_x * sum_x / n);
    lyy = (double)sum_yy - (double)(sum_y * sum_y / n);

    if (lxx == 0) {
        s->ols_r = 1;
        s->ols_a = 9999;
        s->ols_b = s->p[0].x;
        s->ols_angle = M_PI / 2;
        engine_debug ("ols para is: a = %f, b = %f, r = %f, angle = %f, sin = %f\n",
                     s->ols_a, s->ols_b, s->ols_r, s->ols_angle, sin (s->ols_angle));
        return;
    }


    //engine_debug ("lxx = %f, lyy = %f, lxy = %f\n", lxx, lyy, lxy);
    //a = (double) (n * sum_xy - sum_x * sum_y) / (double) (n * sum_xx - sum_x * sum_x);
    //engine_debug ("a = %f\n", a);
    s->ols_a = lxy / lxx;
    s->ols_b = (double) (sum_y / n) - s->ols_a * (double)(sum_x / n);

    //engine_debug ("a = %f, b = %f\n", s->ols_a, s->ols_b);

    for (i = 0; i < n; i++)
      {
        dx = (s->p[i].x - ex);
        dy = (s->p[i].y - ey);

        d_sum_x += dx;
        d_sum_y += dy;
        
        delta = s->p[i].y - (double)(s->ols_a * s->p[i].x + s->ols_b);
        delta_sum = delta * delta;
        dd_sum_x += dx * dx;
        dd_sum_y += dy * dy;
        dd_sum_xy += (dx * dy);
      }

    s_s = sqrt (delta_sum / (n - 2));
    //s->ols_r = (double) (d_sum_x * d_sum_y) / (double)((double)sqrt(dd_sum_x) * (double)sqrt(dd_sum_y));
    s->ols_r = (double) dd_sum_xy / (double) sqrt (dd_sum_x * dd_sum_y);
    //s->ols_r = (double) (sum_xy / n - sum_x / n * sum_y / n) / (double)sqrt ((sum_xx/n -sum_x/n * sum_x/n) * (sum_yy/n - sum_y/n * sum_y/n));

    //s->ols_r = lxy / sqrt(lxx * lyy);
    
    s->ols_angle = atan (s->ols_a);
    engine_debug ("ols para is: a = %f, b = %f, r = %f, s = %f, angle = %f, sin = %f\n\n",
                     s->ols_a, s->ols_b, s->ols_r, s_s, s->ols_angle, sin (s->ols_angle));
}


stroke_type compute_stroke_type (stroke *s)
{
    int n = s->num_p - 1;
    int i;
    double d = 0.0;

    if (s->num_p <  2)
      {
        s->type_s = STROKE_DOT;
        return STROKE_DOT;
      }
    
    for (i = 0; i < n; i++)
      {
        d += hypot (s->p[i + 1].x - s->p[i].x, s->p[i+1].y - s->p[i].y);
        if (d >= DIS_THRD)
            break;
      }

    if (d < DIS_THRD)
      {
        s->type_s = STROKE_DOT;
        return STROKE_DOT;
      }
#if 0  // we will not use this algorithm
    compute_angle (s);  // compute the angle between two adjacent points
    compute_ex_var (s); // compute the variance of the angles
    
    if (s->var_angle < LINE_THRD)
        return STROKE_LINE;
    else 
        return STROKE_CURVE;
#endif

    compute_ols (s); 

    if (fabs(s->ols_r) > OLS_LINE_THRD)
      {
        s->type_s = STROKE_LINE;
        return STROKE_LINE;
      }
    else
      {
        s->type_s = STROKE_CURVE;
        return STROKE_CURVE;
      }
}

int is_stroke_para (stroke *s1, stroke *s2)
{
    double abs_ex_diff = fabs (s1->ex_angle - s2->ex_angle);
    if (abs_ex_diff < PARA_THRD)
        return 1;
    else
        return 0;
}

int is_angle_mono (stroke *s)
{
    return 1;
}

gesture *gesture_new (int n)
{
    if (n < 1)
        return NULL;
    
    gesture *g = malloc (sizeof (gesture));
    //g->s = (stroke *) malloc (n * sizeof (stroke));
   
    g->num_s = 0;
    g->max_num_s = n;
    
    return g;
}

void gesture_del (gesture *g)
{
     free (g);
}

void add_stroke_into_gesture (gesture *g, stroke *s)
{
    g->s[g->num_s] = *s;
    g->num_s ++;
}

void handle_dot_line (gesture *g, gesture_info *g_info)
{
    stroke *s1 = &(g->s[0]);
    stroke *s2 = &(g->s[1]);
    int n1 = s1->num_p;
    int n2 = s2->num_p;
    stroke *s = stroke_new (n1 + n2);
    int i;
    gesture_type g_type = GESTURE_UNDEF;
    double delta_a;
    double a1;
    double a2;
    double d1, d2;
    double a;

    if (s1->type_s == STROKE_DOT)
      {
        add_point (s, s1->p[0]);
        for (i = 0; i < n2; i++)
          {
            add_point (s, s2->p[i]);
          }
      }
    else
      {
        add_point (s, s2->p[0]);
        for (i = 0; i < n1; i++)
          {
            add_point (s, s1->p[i]);
          }

      }

    a1 = atan2 (s->p[0].y - s->p[1].y, s->p[0].x - s->p[1].x);
    a2 = atan2 (s->p[0].y - s->p[s->num_p - 1].y, s->p[0].x - s->p[s->num_p - 1].x);

    d1 = hypot (s->p[0].x - s->p[1].x, s->p[0].y - s->p[1].y);
    d2 = hypot (s->p[0].x - s->p[s->num_p - 1].x, s->p[0].y - s->p[s->num_p - 1].y);

    if (s1->type_s == STROKE_DOT) 
    	a = s2->ols_angle - a1;
    else
	    a = s1->ols_angle - a1;

    if ((fabs(tan (a)) < 0.5) && (fabs (a1 - a2) < 0.2))
      {
        if (d1 > d2)
            g_type = GESTURE_PINCH_IN;
        else
            g_type = GESTURE_PINCH_OUT;
      }

    engine_debug ("------angle1: %f\n", a1);
    engine_debug ("------angle2: %f\n", a2);
    engine_debug ("@@@@ a = %f\n", fabs(tan (a)));


#if 0
    compute_ols (s);

    engine_debug ("------delta angle: %f\n", fabs (s1->ols_angle - s2->ols_angle));
    engine_debug ("------s1 angle: %f\n", (s1->ols_angle));
    engine_debug ("------s2 angle: %f\n", (s2->ols_angle));

    if (fabs(s->ols_r) > OLS_LINE_THRD) {
	    if (s1->type_s == STROKE_DOT) {
 	        if (fabs (s->ols_angle - s2->ols_angle) < 0.4) {
        	    if (hypot (s->p[0].x - s->p[1].x, s->p[0].y - s->p[1].y) > 
 	    	        hypot (s->p[0].x - s->p[s->num_p - 1].x, s->p[0].y - s->p[s->num_p - 1].y))
	    	        g_type = GESTURE_PINCH_IN;
	            else
	                g_type = GESTURE_PINCH_OUT;
	        }
	    }	
	    else {
            if (fabs (s->ols_angle - s1->ols_angle) < 0.4) {
                if (hypot (s->p[0].x - s->p[1].x, s->p[0].y - s->p[1].y) >
                    hypot (s->p[0].x - s->p[s->num_p - 1].x, s->p[0].y - s->p[s->num_p - 1].y))
                    g_type = GESTURE_PINCH_IN;
                else
                    g_type = GESTURE_PINCH_OUT;
            }

	    }
    
    }
#endif

    if (g_type != GESTURE_UNDEF)
      {
        g_info->g_type = g_type;
	    return;
      }

    delta_a = a1 -a2;

    if (delta_a > M_PI)
        delta_a -= 2 * M_PI;
    else if (delta_a < - M_PI)
        delta_a += 2 * M_PI;
    
    if (delta_a > 0.0001)
	    g_type = GESTURE_ROTATE_ACKW;
    else if (delta_a < -0.001)
	    g_type = GESTURE_ROTATE_CKW;
 
    g_info->g_type = g_type;
    g_info->angle = delta_a;

    g_info->center.x = s->p[0].x;
    g_info->center.y = s->p[0].y;

    stroke_del(s);
    return;
}



void handle_pinch (gesture *g, gesture_info *g_info)
{
    stroke *s1 = &(g->s[0]);
    stroke *s2 = &(g->s[1]);
    int n1 = s1->num_p;
    int n2 = s2->num_p;
    int i;
    int num = 0;
    float  max_x, max_y, min_x, min_y;
    double dis = 0.0;
    double angle_dot = 0.0;
    double angle_line = 0.0;
    double delta_angle = 0.0;

    // only compare x, because para to X axis
    if (fabs(s1->ols_a) < X_AXIS_THRD)
      {

	    dis = fabs (s1->ols_b - s2->ols_b);

        if (s1->p[0].x- s1->p[n1-1].x >= 0)
          {
            max_x = s1->p[0].x;
            min_x = s1->p[n1-1].x;
          }   
        else
          {
            max_x = s1->p[n1-1].x;
            min_x = s1->p[0].x;
          }   
        for (i = 0; i < n2; i ++)
          {
            if ((s2->p[i].x >= max_x) || (s2->p[i].x <= min_x))
                num ++;
          }
      }
    // only compare y, because para to Y axis
    else if (fabs (s1->ols_a) > Y_AXIS_THRD)
      {
        dis = fabs (s1->ols_b - s2->ols_b);

        if (s1->p[0].y - s1->p[n1-1].y >= 0)
          {
            max_y = s1->p[0].y;
            min_y = s1->p[n1-1].y;
          }
        else
          {
            max_y = s1->p[n1-1].y;
            min_y = s1->p[0].y;
          }
        for (i = 0; i < n2; i ++)
          {
            if ((s2->p[i].y >= max_y) || (s2->p[i].y <= min_y))
                num ++;
          }

      }
    else
      {
        engine_debug ("non x-axis nor y-axis\n");
        if (s1->p[0].y - s1->p[n1-1].y >= 0)
          {
            max_y = s1->p[0].y;
            min_y = s1->p[n1-1].y;
          }
        else
          {
            max_y = s1->p[n1-1].y;
            min_y = s1->p[0].y;
          }

        if (s1->p[0].x - s1->p[n1-1].x >= 0)
          {
            max_x = s1->p[0].x;
            min_x = s1->p[n1-1].x;
          }
        else
          {
            max_x = s1->p[n1-1].x;
            min_x = s1->p[0].x;
          }
        engine_debug ("min_x = %f, min_y = %f, max_x = %f, max_y = %f\n", min_x, min_y, max_x, max_y);
        for (i = 0; i < n2; i++)
          {
            if (((s2->p[i].x > max_x) || (s2->p[i].x < min_x)) && ((s2->p[i].y > max_y) || (s2->p[i].y <  min_y)))
                num ++;
          }
      }
  
    engine_debug ("total number = %d, num matched = %d\n", n2, num);

    angle_dot = atan2 (s1->p[(n1 - 1)/2].y - s2->p[(n2 - 1)/2].y, s1->p[(n1 - 1)/2].x - s2->p[(n2 - 1)/2].x);
    dis = hypot (s1->p[(n1 - 1)/2].x - s2->p[(n2 - 1)/2].x, s1->p[(n1 - 1)/2].y - s2->p[(n2 - 1)/2].y);

    if (angle_dot > M_PI/2)
	    angle_dot = M_PI - angle_dot;

    if (angle_dot < -M_PI/2)
        angle_dot = M_PI + angle_dot;

    angle_line = (s1->ols_angle + s2->ols_angle) / 2;
    
    if (angle_line > M_PI/2)
        angle_line = M_PI - angle_line;

    if (angle_line < -M_PI/2)
        angle_line = M_PI + angle_line;

    engine_debug ("p-p distance is %f\n", dis);
    dis = dis * fabs (sin (angle_line - angle_dot));

    engine_debug ("dis = %f, angle_line = %f, angle_dot = %f\n", dis, angle_line, angle_dot);

    if (dis > 60.0)
      {
        delta_angle = atan2 (s1->p[0].y - s1->p[0].y,s1->p[0].x - s2->p[0].x) -
                      atan2 (s1->p[s1->num_p - 1].y - s2->p[s2->num_p - 1].y,s1->p[s1->num_p - 1].x - s2->p[s2->num_p -1].x);

	    //fix me, the direction is not right
        if (delta_angle > M_PI)
            delta_angle -= 2 * M_PI;
        else if (delta_angle < - M_PI)
            delta_angle += 2 * M_PI;

        if (delta_angle > 0.0001)
            g_info->g_type = GESTURE_ROTATE_ACKW;
        else if (delta_angle < -0.001)
            g_info->g_type = GESTURE_ROTATE_CKW;
        return;
      }
    
    if (num >= s2->num_p -1)
      {
        if (hypot (s1->p[0].x - s2->p[0].x, s1->p[0].y - s2->p[0].y) <
            hypot (s1->p[n1-1].x - s2->p[n2-1].x, s1->p[n1-1].y - s2->p[n2-1].y))
          {
            g_info->g_type = GESTURE_PINCH_OUT;
          }
        else
            g_info->g_type = GESTURE_PINCH_IN;
      }
    else
      {
        g_info->g_type = GESTURE_UNDEF;
      }
    return;
}

void handle_rotate (gesture *g, gesture_info *g_info)
{
    stroke *s1 = &(g->s[0]);
    stroke *s2 = &(g->s[1]);
    int n1 = s1->num_p;
    int n2 = s2->num_p;
    int angle_ckw1 = 0;
    int angle_ckw2 = 0;
    int i;
    double delta_angle;
    int trend_up = 0;
    int trend_down = 0;
    int trend_zero = 0;

    //engine_debug ("gesture recog: stroke type = %d, %d\n", s1->type_s, s2->type_s);

    if (s1->type_s == STROKE_CURVE)
      {

        engine_debug ("stroke 1\n");
        compute_angle (s1);
        
        for (i = 0; i < n1 - 1; i ++)
          {
            
            delta_angle = s1->p[i+1].angle - s1->p[i].angle; 

            if (delta_angle > M_PI)
                delta_angle -= 2 * M_PI;
            else if (delta_angle < - M_PI)
                delta_angle += 2 * M_PI;

            if (fabs (delta_angle) < 0.1)
                delta_angle = 0;


            //if ((delta_angle <= 0.05) || (delta_angle >= -0.05))
            //    delta_angle = 0.0;
            //engine_debug ("delta_angle = %f\n", delta_angle);

            if (delta_angle > 0) 
                trend_up += 1;
            else if (delta_angle < 0)
                trend_down += 1;
            else
                trend_zero += 1;
          }
    
        engine_debug ("up = %d, down = %d, zero = %d\n", trend_up, trend_down, trend_zero);
    
        if ((trend_up + trend_zero) >= trend_down * 2)
            angle_ckw1 = 1;
        else if ((trend_down + trend_zero) >= trend_up * 2)
            angle_ckw1 = 0;
        else
          {
            g_info->g_type = GESTURE_UNDEF;
            return;
          }

      }

    trend_up = 0;
    trend_down = 0;
    trend_zero = 0;

    if (s2->type_s == STROKE_CURVE)
      {

        engine_debug ("stroke 2 \n");
        compute_angle (s2);

        for (i = 0; i < n2 - 1; i ++)
          {
            delta_angle = s2->p[i+1].angle - s2->p[i].angle;

            if (delta_angle > M_PI)
                delta_angle -= 2 * M_PI;
            else if (delta_angle < - M_PI)
                delta_angle += 2 * M_PI;

            if (fabs (delta_angle) < 0.1)
                delta_angle = 0;

            //engine_debug ("delta_angle = %f\n", delta_angle);
            
            if (delta_angle > 0) 
                trend_up += 1;
            else if (delta_angle < 0)
                trend_down += 1;
            else
                trend_zero += 1;
          }

        engine_debug ("up = %d, down = %d, zero = %d\n", trend_up, trend_down, trend_zero);

        if (((trend_up + trend_zero) >= trend_down * ARCH_THRD) && (trend_up > trend_down))
            angle_ckw2 = 1;
        else if (((trend_down + trend_zero) >= trend_up * ARCH_THRD) && (trend_down > trend_up))
            angle_ckw2 = 0;
        else
          {            
            g_info->g_type = GESTURE_UNDEF;
            return;
          }

      }

    if (s1->type_s == STROKE_CURVE)
      {
        if (s2->type_s == STROKE_CURVE)
          {
            if (angle_ckw1 + angle_ckw2 == 2)
                g_info->g_type = GESTURE_ROTATE_CKW;
            else if (angle_ckw1 + angle_ckw2 == 0)
                g_info->g_type = GESTURE_ROTATE_ACKW;
            else
                g_info->g_type = GESTURE_UNDEF;
          }
        else
          {
            if (angle_ckw1 == 1)
                g_info->g_type = GESTURE_ROTATE_CKW;
            else 
                g_info->g_type = GESTURE_ROTATE_ACKW;
          }
      }
    else
      {
        if (angle_ckw2 == 1)
            g_info->g_type = GESTURE_ROTATE_CKW;
        else 
            g_info->g_type = GESTURE_ROTATE_ACKW;
      }

    return;
}

void gesture_recog (gesture *g, gesture_info *g_info)
{
    stroke *s1 = &(g->s[0]);
    stroke *s2 = &(g->s[1]);
    float s1_delta_x;
    float s1_delta_y;
    float s2_delta_x;
    float s2_delta_y;
    int n1 = s1->num_p;
    int n2 = s2->num_p;
 
    //engine_debug ("gesture recog: stroke type = %d, %d\n", s1->type_s, s2->type_s);

    if (((s1->type_s == STROKE_DOT) && (s2->type_s == STROKE_DOT)) || 
        ((s1->type_s == STROKE_LINE) && (s2->type_s == STROKE_CURVE)) ||
        ((s1->type_s == STROKE_CURVE) && (s2->type_s == STROKE_LINE)))
        g_info->g_type =  GESTURE_UNDEF;
    
    else if (((s1->type_s == STROKE_DOT) && (s2->type_s == STROKE_LINE)) || 
             ((s1->type_s == STROKE_LINE) && (s2->type_s == STROKE_DOT)))
      {
        handle_dot_line (g, g_info);
      }

    else if (((s1->type_s == STROKE_LINE) && (s2->type_s == STROKE_LINE)))
      {
        if (fabs(s1->ols_angle - s2->ols_angle) > PARA_THRD)
          {
            //TODO, We can do more to recogise more gestures
            g_info->g_type = GESTURE_UNDEF;
          }

        s1_delta_x = s1->p[n1 - 1].x - s1->p[0].x;
        s1_delta_y = s1->p[n1 - 1].y - s1->p[0].y;
        s2_delta_x = s2->p[n2 - 2].x - s2->p[0].x;
        s2_delta_y = s2->p[n2 - 2].y - s2->p[0].y;

	engine_debug ("x1[n] = %f, y1[n] = %f, x2[n] = %f, y2[n] = %f\n",
          s1->p[n1 - 1].x , s1->p[n1 - 1].y , s2->p[n2 - 1].x , s2->p[n2 - 1].y );
	engine_debug ("x1[0] = %f, y1[0] = %f, x2[0] = %f, y2[0] = %f\n",
                       s1->p[0].x , s1->p[0].y , s2->p[0].x , s2->p[0].y );
	engine_debug ("n1 = %d, n2 = %d\n", n1, n2);
        engine_debug ("x1= %f, y1 = %f, x2 = %f, y2 = %f\n", s1_delta_x, s1_delta_y, s2_delta_x, s2_delta_y);

        if (s1->ols_a < X_AXIS_THRD || s2->ols_a < X_AXIS_THRD)
          {
            if (s1_delta_x * s2_delta_x > 0)
                g_info->g_type = GESTURE_MT_NAVIGATE;
          }
        else if (s1->ols_a > Y_AXIS_THRD || s2->ols_a > Y_AXIS_THRD)
          {
            if (s1_delta_y * s2_delta_y > 0)
                g_info->g_type = GESTURE_MT_NAVIGATE;
          }
        else
          {
            if ((s1_delta_x * s2_delta_x > 0) || (s1_delta_y * s2_delta_y > 0))
            g_info->g_type = GESTURE_MT_NAVIGATE;
          }
        
        handle_pinch (g, g_info);
              
      }
    
    /*
    else if (((s1->type_s == STROKE_DOT) && (s2->type_s == STROKE_CURVE)) ||
             ((s1->type_s == STROKE_CURVE) && (s2->type_s == STROKE_DOT)) ||
             ((s1->type_s == STROKE_CURVE) && (s2->type_s == STROKE_CURVE)))
    */
    else
      {
        handle_rotate (g, g_info);
      }

    return;               
}


void gesture_process (GSList *list1, GSList *list2, gesture_info *g_info)
{
    stroke_type s_type;
    stroke_type s_type_1;

    stroke *a = stroke_new (MAX_P_LEN);
    stroke *b = stroke_new (MAX_P_LEN);
    gesture *g = gesture_new (2);

    memset (g_info, 0, sizeof (gesture_info));

    GSList *l;


    coor *point;

    for (l = list1; l; l = l->next)
      {
        point = l->data;
      }
    
    for (l = list2; l; l = l->next)
      {
        point = l->data;
      }

    add_stroke_into_gesture (g, a);
    add_stroke_into_gesture (g, b);

    add_point_glist (&(g->s[0]), list1);
    add_point_glist (&(g->s[1]), list2);

    s_type = compute_stroke_type (g->s);
    s_type_1 = compute_stroke_type (&(g->s[1]));


    engine_debug ("stroke 1 type is: ");
    if (s_type == STROKE_DOT)
        engine_debug ("dot\n");
    else if (s_type == STROKE_LINE)
        engine_debug ("line\n");
    else
        engine_debug ("curve\n");

    engine_debug ("stroke 2 type is: ");
 
    if (s_type_1 == STROKE_DOT)
        engine_debug ("dot\n");
    else if (s_type_1 == STROKE_LINE)
        engine_debug ("line\n");
    else
        engine_debug ("curve\n");

    gesture_recog (g, g_info);

    stroke_del (a);
    stroke_del (b);
    gesture_del (g);
    return;
}

#if 0
gesture_type gesture_process (GSList *list1, GSList *list2)
{
  coor *point;

  for (; list1; list1 = list1->next)
    {
      point = list1->data;
      engine_debug("list1: x/y is %d/%d\n", point->x, point->y);
    }
  for (; list2; list2 = list2->next)
    {
      point = list2->data;
      engine_debug("list2: x/y is %d/%d\n", point->x, point->y);
    }

  return 0;
//  engine_debug();
}
#endif
