#define _DEFAULT_SOURCE // usleep()
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <sys/epoll.h>
#include <sys/inotify.h>
// #include "inotify-syscalls.h"
#include "include/raylib.h"
#include "include/raymath.h"
#include "boids_game.h"

#define SCREEN_WIDTH 1300
#define SCREEN_HEIGHT 1080
#define TARGET_FPS 60

const char *GAME_LIB = "./libboids.so";
char epoll_buf[1024];

struct Game {
    void *handle;
    struct GameApi api;
    struct GameState *state;
};
#define MAX_EVENTS 1

int main(void) {
    int fd = inotify_init();
    if (fd < 0) {
        fprintf(stderr, "Error initializing inotify\n");
    }
    int wd;
    wd = inotify_add_watch(fd, GAME_LIB, IN_MODIFY);

    // create epoll instance
    int epollfd = epoll_create1(0);
    if (epollfd == -1) {
        fprintf(stderr, "Error creating epoll instance\n");
    }

    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = fd;

    // register inotify fd with epoll
    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event) == -1) {
        fprintf(stderr, "Error adding inotify descriptor to epoll\n");
    }

    InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Boids");

    SetTargetFPS(TARGET_FPS);

    struct epoll_event events[MAX_EVENTS];

    while (!WindowShouldClose()) {
        int nfds = epoll_wait(epollfd, events, MAX_EVENTS, 0);
        if (nfds == -1) {
            fprintf(stderr, "epoll_wait failed\n");
            break;
        }

        for (int n = 0; n < nfds; ++n) {
            if (events[n].data.fd == fd) {
                printf("SO has been updated!\n");
                read(fd, epoll_buf, sizeof(epoll_buf));
            }
        }

        BeginDrawing();
        ClearBackground(BEIGE);
        EndDrawing();
    }

    inotify_rm_watch(fd, wd);
    close(fd);
    close(epollfd);
    CloseWindow();
}
