/*
 * Copyright © 2022 Codethink Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "evdev_input.h"
#include "input_common.h"
#include <fcntl.h>
#include <linux/input.h>
#include <unistd.h>

int get_evdev_fd(int *fd, int event) {
  char eventLocation[255];
  snprintf(eventLocation, 255, "/dev/input/event%d", event);
  *fd = open(eventLocation, O_RDWR);
  if (*fd < 0) {
    int err = errno;
    fprintf(stderr, "Could not open file %s: %s\n", eventLocation,
            strerror(err));
    return 0;
  }
  return 1;
}

void evdev_input_backend(qad_backend_input_t *backend) {
  backend->move = evdev_input_move;
  backend->button = evdev_input_button;
  backend->touch = evdev_input_touch;
  backend->swipe = evdev_input_swipe;
  backend->key = evdev_input_key;
  backend->text = evdev_input_text;
}

int evdev_input_move(int x, int y, int event) {
  int fd;
  if (!get_evdev_fd(&fd, event)) {
    return -1;
  }
  if (send_position_event_mt(x, y, fd) < 0) {
    close(fd);
    return -1;
  }

  int res = send_syn_event(fd);
  close(fd);
  return res;
}

int evdev_input_button(int value, int event) {
  int fd;
  if (!get_evdev_fd(&fd, event)) {
    return -1;
  }

  int tracking_event = 100;
  if (value == 0)
    tracking_event = -1;

  if (send_tracking_event(tracking_event, fd) < 0) {
    close(fd);
    return -1;
  }

  if (send_button_event(value, fd) < 0) {
    close(fd);
    return -1;
  }

  int res = send_syn_event(fd);
  close(fd);

  return res;
}

int evdev_input_touch(int x, int y, int duration, int event) {
  int fd;
  if (!get_evdev_fd(&fd, event)) {
    return -1;
  }

  int res = send_touch(x, y, duration, fd);
  close(fd);

  return res;
}

int evdev_input_swipe(int x, int y, int x_2, int y_2, int velocity, int event,
                      int stop) {
  int fd;
  if (!get_evdev_fd(&fd, event)) {
    return -1;
  }

  int res = send_swipe(x, y, x_2, y_2, velocity, fd, stop);
  close(fd);

  return res;
}

int evdev_input_key(int key, int event) {
  int fd;
  if (!get_evdev_fd(&fd, event)) {
    return -1;
  }

  int res = send_key_event(key, fd);
  QAD_CHECK_ERR(res);
  res = send_syn_event(fd);
  close(fd);
  return res;
}

int evdev_input_text(int const *keycodes, int num_keycodes, int event) {
  int fd;
  if (!get_evdev_fd(&fd, event)) {
    return -1;
  }

  int res = send_text_event(keycodes, num_keycodes, fd);
  QAD_CHECK_ERR(res);
  close(fd);

  return res;
}
