#include <engine.h>
#include <data_struct/queue.h>
//should have a event structure, and a system can subscribe to an event, then whenever the event is triggered by a system, subscriber system should receive a signal.

typedef struct {
	void*		(*callback)(Event);
	EVENT_TYPE	type;
}	listener_t;

//static Event *queue;
static queue_t	queue;
pthread_mutex_t	qmtx;

#define MAX_LISTENER	100
#define QUEUE_SIZE		1000

listener_t	listener[MAX_LISTENER];
static int	current_listener = 0;

void	EventInit(void) {
	void* buffer = calloc(QUEUE_SIZE, sizeof(Event));
	assert(buffer);
	queue_init_static(&queue, buffer, QUEUE_SIZE, sizeof(Event));
	assert(pthread_mutex_init(&qmtx, NULL));
}

void	EventFree(void) {
	free(queue.data);
	pthread_mutex_destroy(qmtx);
	queue_free(&queue);
}

void	EventSubscribe(const int event_type, void (*callback)(Event)) {
	//this should return an handle that allow to poll event that happen last frame
	listener[current_listener].callback = callback;
	listener[current_listener].type = event_type;
	current_listener++;
}

void	EventEmit(Event event) {
	printf("Event Emited");
	while (pthread_mutex_trylock(qmtx) != 0) {
		usleep(20);
	}
	if (!queue_push(&queue, &event)) {
		printf("EventQueue is Full !! add more space to it");
	}
	pthread_mutex_unlock(qmtx);
}

void	EventUpdate() {
	Event event;
	//process all the queue each update
	while (queue_pop(&queue, &event)) {
		//notify each susbscriber of the event
		for (int i = 0; i < MAX_LISTENER; i++) {
			if (event.type == listener[i].type) {
				//send to listener's
				listener->callback(event);
			}
		}
		printf("%lf, %s", event.time, event.info);//need to convert unix time to timestamp
	}
}
