#include "sormc.h"
#include <fcntl.h>
#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define MAX_DEVICES 32
#define DEVICE_PATH "/dev/input/event"

int is_keyboard(int fd) {
    char device_name[256] = {0};

    if (ioctl(fd, EVIOCGNAME(sizeof(device_name)), device_name) < 0) {
        return 0;
    }

    return strstr(device_name, "keyboard") != NULL;
}

int main() {

    int db = sormc("tikker.db");

    ulonglong times_repeated = 0;
    ulonglong times_pressed = 0;
    ulonglong times_released = 0;

    sormq(db, "CREATE TABLE IF NOT EXISTS kevent (id INTEGER PRIMARY KEY AUTOINCREMENT, code,event,name,timestamp)");

    int keyboard_fds[MAX_DEVICES];
    int num_keyboards = 0;

    for (int i = 0; i < MAX_DEVICES; i++) {
        char device_path[32];
        snprintf(device_path, sizeof(device_path), "%s%d", DEVICE_PATH, i);

        int fd = open(device_path, O_RDONLY);
        if (fd < 0) {
            continue;
        }

        if (is_keyboard(fd)) {
            keyboard_fds[num_keyboards++] = fd;
            printf("Found keyboard: %s\n", device_path);
        } else {
            close(fd);
        }
    }

    if (num_keyboards == 0) {
        fprintf(stderr, "No keyboard found.\n");
        return 1;
    }

    printf("Monitoring %d keyboards.\n", num_keyboards);

    struct input_event ev;
    fd_set read_fds;

    while (1) {
        FD_ZERO(&read_fds);
        int max_fd = -1;

        for (int i = 0; i < num_keyboards; i++) {
            FD_SET(keyboard_fds[i], &read_fds);
            if (keyboard_fds[i] > max_fd) {
                max_fd = keyboard_fds[i];
            }
        }

        if (select(max_fd + 1, &read_fds, NULL, NULL, NULL) < 0) {
            perror("select error");
            break;
        }

        for (int i = 0; i < num_keyboards; i++) {
            if (FD_ISSET(keyboard_fds[i], &read_fds)) {
                ssize_t bytes = read(keyboard_fds[i], &ev, sizeof(struct input_event));

                if (bytes == sizeof(struct input_event)) {
                    if (ev.type == EV_KEY) {
                        char key_name[256];
                        ioctl(keyboard_fds[i], EVIOCGNAME(sizeof(key_name)), key_name);

                        printf("Keyboard: %s, ", key_name);
                        char *event_name = NULL;
                        if (ev.value == 1) {
                            event_name = "PRESSED";
                            times_pressed++;
                        } else if (ev.value == 0) {
                            event_name = "RELEASED";
                            times_released++;
                        } else {
                            event_name = "REPEATED";
                            times_repeated++;
                        }

                        sormq(db, "INSERT INTO kevent (code, event, name,timestamp) VALUES (%d, %s, %s, DATETIME('now'))", ev.code,
                              event_name, key_name);
                        printf("Event: %s, ", ev.value == 1 ? "PRESSED" : ev.value == 0 ? "RELEASED" : "REPEATED");
                        printf("Key Code: %d ", ev.code);
                        printf("Pr: %lld Rel: %lld Rep: %lld\n", times_pressed, times_released, times_repeated);
                    }
                }
            }
        }
    }

    for (int i = 0; i < num_keyboards; i++) {
        close(keyboard_fds[i]);
    }

    return 0;
}