/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/limits.h>
#include <sys/poll.h>

#include <memory>

#include <android/log.h>

static struct pollfd* ufds;
static char** device_names;
static int nfds;

static int open_device(const char* device) {
  int version;
  int fd;
  struct pollfd* new_ufds;
  char** new_device_names;
  char name[80];
  char location[80];
  char idstr[80];
  struct input_id id;

  fd = open(device, O_RDWR);
  if (fd < 0) {
    return -1;
  }

  if (ioctl(fd, EVIOCGVERSION, &version)) {
    return -1;
  }
  if (ioctl(fd, EVIOCGID, &id)) {
    return -1;
  }
  name[sizeof(name) - 1] = '\0';
  location[sizeof(location) - 1] = '\0';
  idstr[sizeof(idstr) - 1] = '\0';
  if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
    name[0] = '\0';
  }
  if (ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
    location[0] = '\0';
  }
  if (ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
    idstr[0] = '\0';
  }

  new_ufds = reinterpret_cast<pollfd*>(realloc(ufds, sizeof(ufds[0]) * (nfds + 1)));
  if (new_ufds == NULL) {
    fprintf(stderr, "out of memory\n");
    return -1;
  }
  ufds = new_ufds;
  new_device_names = reinterpret_cast<char**>(realloc(
      device_names, sizeof(device_names[0]) * (nfds + 1)));
  if (new_device_names == NULL) {
    fprintf(stderr, "out of memory\n");
    return -1;
  }
  device_names = new_device_names;
  ufds[nfds].fd = fd;
  ufds[nfds].events = POLLIN;
  device_names[nfds] = strdup(device);
  nfds++;

  return 0;
}

int close_device(const char* device) {
  int i;
  for (i = 1; i < nfds; i++) {
    if (strcmp(device_names[i], device) == 0) {
      int count = nfds - i - 1;
      free(device_names[i]);
      memmove(device_names + i, device_names + i + 1, sizeof(device_names[0]) * count);
      memmove(ufds + i, ufds + i + 1, sizeof(ufds[0]) * count);
      nfds--;
      return 0;
    }
  }
  return -1;
}

static int read_notify(const char* dirname, int nfd) {
  int res;
  char devname[PATH_MAX];
  char* filename;
  char event_buf[512];
  int event_size;
  int event_pos = 0;
  struct inotify_event *event;

  res = read(nfd, event_buf, sizeof(event_buf));
  if (res < (int)sizeof(*event)) {
    if (errno == EINTR)
      return 0;
    fprintf(stderr, "could not get event, %s\n", strerror(errno));
    return 1;
  }

  strcpy(devname, dirname);
  filename = devname + strlen(devname);
  *filename++ = '/';

  while (res >= (int)sizeof(*event)) {
    event = reinterpret_cast<struct inotify_event*>(event_buf + event_pos);
    if (event->len) {
      strcpy(filename, event->name);
      if (event->mask & IN_CREATE) {
        open_device(devname);
      } else {
        close_device(devname);
      }
    }
    event_size = sizeof(*event) + event->len;
    res -= event_size;
    event_pos += event_size;
  }
  return 0;
}

static int scan_dir(const char* dirname) {
  char devname[PATH_MAX];
  char* filename;
  struct dirent* de;
  std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dirname), closedir);
  if (dir == NULL)
    return -1;
  strcpy(devname, dirname);
  filename = devname + strlen(devname);
  *filename++ = '/';
  while ((de = readdir(dir.get()))) {
    if ((de->d_name[0] == '.' && de->d_name[1] == '\0') ||
        (de->d_name[1] == '.' && de->d_name[2] == '\0'))
      continue;
    strcpy(filename, de->d_name);
    open_device(devname);
  }
  return 0;
}

int init_getevent() {
  int res;
  const char* device_path = "/dev/input";

  nfds = 1;
  ufds = reinterpret_cast<pollfd*>(calloc(1, sizeof(ufds[0])));
  ufds[0].fd = inotify_init();
  ufds[0].events = POLLIN;

  res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE);
  if (res < 0) {
    return 1;
  }
  res = scan_dir(device_path);
  if (res < 0) {
    return 1;
  }
  return 0;
}

void uninit_getevent() {
  int i;
  for (i = 0; i < nfds; i++) {
    close(ufds[i].fd);
  }
  free(ufds);
  ufds = 0;
  nfds = 0;
}

int get_event(struct input_event* event, int timeout) {
  int res;
  int i;
  int pollres;
  const char* device_path = "/dev/input";
  while (1) {
    pollres = poll(ufds, nfds, timeout);
    if (pollres == 0) {
      return 1;
    }
    if (ufds[0].revents & POLLIN) {
      read_notify(device_path, ufds[0].fd);
    }
    for (i = 1; i < nfds; i++) {
      if (ufds[i].revents) {
        if (ufds[i].revents & POLLIN) {
          res = read(ufds[i].fd, event, sizeof(*event));
          if (res < static_cast<int>(sizeof(event))) {
            fprintf(stderr, "could not get event\n");
            return -1;
          }
          return 0;
        }
      }
    }
  }
  return 0;
}
