#include "events.h"
#include "mem.h"
#include "bctypes.h"
#include "interrupts.h"

// Pointer to the first event
struct TaskTree *events = NULL;

struct TaskTree *event_list_head()
{
	return events;
}

struct TaskTree *event_list_next(struct TaskTree *e)
{
	return e->data.event.next;
}

void remove_event(struct TaskTree *e)
{
	// Update return pointer of the next node
	if (e->data.event.next != NULL) {
		e->data.event.next->ptr = e->ptr;
	}

	// Update the next pointer of the previous node
	if (e->ptr != NULL) {
		e->ptr->data.event.next = e->data.event.next;
	} else {
		events = e->data.event.next;
	}

	e->trash = true;
}

void register_events(struct MTask *t, struct TaskTree *tt)
{
	// Register Event
	struct TaskTree *e = mem_alloc_tree();
	e->task_type = BCEvent_c;
	e->trash = false;
	e->ptr = NULL;
	e->data.event.next = events;
	e->data.event.task_id = t->taskid;

	if (events != NULL) {
		events->ptr = e;
	}
	events = e;

	switch (tt->task_type) {
		case BCInterrupt_c:
			e->data.event.event_type = tt->data.interrupt.pin * 5 +
						   tt->data.interrupt.mode;
			//Enable interrupt
			enable_interrupt(tt->data.interrupt.pin,
					 tt->data.interrupt.mode);
			break;
		default:
			break;
	}
}

void deregister_events(struct MTask *t, struct TaskTree *tt)
{
	switch (tt->task_type) {
		case BCInterrupt_c: {
			uint16_t pin = tt->data.interrupt.pin;
			enum InterruptMode mode = tt->data.interrupt.mode;

			struct TaskTree *e = event_list_head();
			uint16_t event_type = pin * 5 + mode;

			while (e != NULL) {
				if (e->data.event.event_type == event_type &&
					e->data.event.task_id == t->taskid) {
					remove_event(e);
					disable_interrupt(pin, mode);
					return;
				}
				e = event_list_next(e);
			}
			} break;
		default:
			break;
	}
}
