/**
 * @file check_gesture_attrs.c
 * @brief Unit tests for GEIS v1 gesture attrs
 *
 * Copyright 2011 Canonical Ltd.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of version 3 of the GNU Lesser General Public License as published
 * by the Free Software Foundation.
 *
 * 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 program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */
#include <check.h>

#include <geis/geis.h>
#include <math.h>
#include <stdio.h>
#include <string.h>

#define GEIS_TEST_WINDOW geis_win_type_str(Test)

static const char* s_gestures[] = {
  GEIS_GESTURE_TYPE_DRAG2, GEIS_GESTURE_TYPE_DRAG3,
  GEIS_GESTURE_TYPE_PINCH2, GEIS_GESTURE_TYPE_PINCH3,
  GEIS_GESTURE_TYPE_ROTATE2, GEIS_GESTURE_TYPE_ROTATE3,
  GEIS_GESTURE_TYPE_TAP2, GEIS_GESTURE_TYPE_TAP3, GEIS_GESTURE_TYPE_TAP4,
  NULL
};

struct test_data_t
{
  int count_728606;
  int count_732104;
};

static void
gesture_added(void            *cookie CK_ATTRIBUTE_UNUSED,
              GeisGestureType  gesture_type CK_ATTRIBUTE_UNUSED,
              GeisGestureId    gesture_id CK_ATTRIBUTE_UNUSED,
              GeisSize         attr_count CK_ATTRIBUTE_UNUSED,
              GeisGestureAttr *attrs CK_ATTRIBUTE_UNUSED)
{
}

static void
gesture_removed(void              *cookie CK_ATTRIBUTE_UNUSED,
                GeisGestureType    gesture_type CK_ATTRIBUTE_UNUSED,
                GeisGestureId      gesture_id CK_ATTRIBUTE_UNUSED,
                GeisSize           attr_count CK_ATTRIBUTE_UNUSED,
                GeisGestureAttr   *attrs CK_ATTRIBUTE_UNUSED)
{
}

/*
 * Checks for special values generated by the mock back end.
 */
static void
gesture_start(void              *cookie,
              GeisGestureType    gesture_type CK_ATTRIBUTE_UNUSED,
              GeisGestureId      gesture_id CK_ATTRIBUTE_UNUSED,
              GeisSize           attr_count,
              GeisGestureAttr   *attrs)
{
  GeisSize i;
  struct test_data_t *test_data = (struct test_data_t*)cookie;

  for (i = 0; i < attr_count; ++i)
  {
    if (0 == strcmp(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X)
     && fabs(attrs[i].float_val - 123.456) < 0.01)
    {
      ++test_data->count_728606;
    }
    else if (0 == strcmp(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y)
     && fabs(attrs[i].float_val - 987.654) < 0.01)
    {
      ++test_data->count_728606;
    }
    else if (0 == strcmp(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES)
     && attrs[i].integer_val == 1)
    {
      ++test_data->count_732104;
    }
  }
}

static void
gesture_update(void              *cookie CK_ATTRIBUTE_UNUSED,
               GeisGestureType    gesture_type CK_ATTRIBUTE_UNUSED,
               GeisGestureId      gesture_id CK_ATTRIBUTE_UNUSED,
               GeisSize           attr_count CK_ATTRIBUTE_UNUSED,
               GeisGestureAttr   *attrs CK_ATTRIBUTE_UNUSED)
{
}

static void
gesture_finish(void              *cookie CK_ATTRIBUTE_UNUSED,
               GeisGestureType    gesture_type CK_ATTRIBUTE_UNUSED,
               GeisGestureId      gesture_id CK_ATTRIBUTE_UNUSED,
               GeisSize           attr_count CK_ATTRIBUTE_UNUSED,
               GeisGestureAttr   *attrs CK_ATTRIBUTE_UNUSED)
{
}


GeisGestureFuncs gesture_funcs = {
  gesture_added,
  gesture_removed,
  gesture_start,
  gesture_update,
  gesture_finish
};

/* fixtures */
static GeisInstance g_instance;

/* fixture setup */
static void
construct_instance()
{
  GeisStatus   status;
  GeisXcbWinInfo x_win_info = {
    .display_name  = NULL,
    .screenp       = NULL,
    .window_id     = 1
  };
  GeisWinInfo  win_info = { GEIS_TEST_WINDOW, &x_win_info };

  status = geis_init(&win_info, &g_instance);
}

/* fixture teardown */
static void
destroy_instance()
{
  geis_finish(g_instance);
}

START_TEST(receive_events)
{
  GeisStatus status;
  struct test_data_t test_data;
  memset(&test_data, 0, sizeof(test_data));

  status = geis_subscribe(g_instance,
                          GEIS_ALL_INPUT_DEVICES,
                          s_gestures,
                          &gesture_funcs,
                          &test_data);
  fail_unless(status == GEIS_STATUS_SUCCESS, "subscription failed");

  while (GEIS_STATUS_CONTINUE == geis_event_dispatch(g_instance))
    ;

  /* Regression test for bug LP: #728606. */
  fail_unless(test_data.count_728606 == 2,
              "unexpected count for LP:728606: expected 2, got %d", test_data.count_728606);
  fail_unless(test_data.count_732104 == 0,
              "unexpected count for LP:732104: expected 0, got %d", test_data.count_732104);
}
END_TEST


Suite *
geis1_gesture_attrs_new()
{
  Suite *s = suite_create("geis1_gesture_attrs");
  TCase *test;

  test = tcase_create("lp728606");
  tcase_add_checked_fixture(test, construct_instance, destroy_instance);
  tcase_add_test(test, receive_events);
  suite_add_tcase(s, test);

  return s;
}

