#include <irq/irq.h>
#include <libk/rbtree.h>
#include <libk/std.h>
#include <mm/liballoc.h>
#include <sync/spin_lock.h>
#include <sys/debug.h>

#if defined(__x86_64__)
#include <amd64/apic.h>
#include <amd64/intr.h>
#endif

static struct rb_node_link* irq_tree = NULL;
static spin_lock_t irqs_lock = SPIN_LOCK_INIT;

bool irq_attach (irq_func_t func, void* arg, uint32_t irq_num) {
  struct irq* irq = malloc (sizeof (*irq));
  if (irq == NULL) {
    return false;
  }

  irq->func = func;
  irq->arg = arg;
  irq->irq_num = irq_num;

  spin_lock (&irqs_lock);
  rbtree_insert (struct irq, &irq_tree, &irq->irq_tree_link, irq_tree_link, irq_num);
  spin_unlock (&irqs_lock);

  return true;
}

void irq_detach (uint32_t irq_num) {
  struct irq* irq = irq_find (irq_num);

  spin_lock (&irqs_lock);
  rbtree_delete (&irq_tree, &irq->irq_tree_link);
  spin_unlock (&irqs_lock);

  free (irq);
}

struct irq* irq_find (uint32_t irq_num) {
  struct irq* irq = NULL;

  spin_lock (&irqs_lock);
  rbtree_find (struct irq, &irq_tree, irq_num, irq, irq_tree_link, irq_num);
  spin_unlock (&irqs_lock);

  return irq;
}
