#include <sys/event.h>
#include "seobeo/seobeo.h"


void *Seobeo_Web_Edge_Worker(void *vargs)
{
  WorkerArgs *args = vargs;
  struct kevent evlist[64];
  while (1) {
    int ne = kevent(args->evfd, NULL, 0, evlist, 64, NULL);
    if (ne < 0) continue;
    for (int i = 0; i < ne; i++) {
      Seobeo_PHandle h = evlist[i].udata;
      if (h == args->srv) {
        Seobeo_PHandle cli =
          Seobeo_Stream_Handle_Accept(args->srv);
        if (!cli) continue;
        struct kevent kev = {
          .ident  = cli->socket,
          .filter = EVFILT_READ,
          .flags  = EV_ADD | EV_ONESHOT,
          .udata  = cli
        };
        kevent(args->evfd, &kev, 1, NULL, 0, NULL);
      } else {
        if (h != args->srv) {
          struct kevent kev = {
            .ident  = h->socket,
            .filter = EVFILT_READ,
            .flags  = EV_DELETE,
          };
          kevent(args->evfd, &kev, 1, NULL, 0, NULL); // Remove from kqueue first
        
          Seobeo_Web_HandleClientRequest(h, args->cache); // this frees 
        }
      }
    }
  }
  return NULL;
}

void  Seobeo_Web_Edge(
    Seobeo_PHandle p_server_handle,
    int            thread_count,
    Dowa_PHashMap  p_html_cache)
{
  int kq = kqueue();
  struct kevent kev = {
    .ident  = p_server_handle->socket,
    .filter = EVFILT_READ,
    .flags  = EV_ADD,
    .udata  = p_server_handle
  };
  kevent(kq, &kev, 1, NULL, 0, NULL);

  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setstacksize(&attr, 100 * 1024 * 1024); // 100 MB

  pthread_t  threads[thread_count];
  for (int i = 0; i < thread_count; i++)
  {
    WorkerArgs *args = malloc(sizeof(WorkerArgs));
    *args = (WorkerArgs){ p_server_handle, p_html_cache, kq };

    pthread_create(&threads[i], NULL, Seobeo_Web_Edge_Worker, args);
  }
  for (int i = 0; i < thread_count; i++)
  {
    pthread_join(threads[i], NULL);
  }
  return;
}
