#include "events.h"
#include "main.h"
#include "user_inputs.h"
#include <stdint.h>

static volatile EventQueue event_queue = {.read_idx = 0, .write_idx = 0};

void event_push(Event *ev) {
  if (event_num_free() == 0) {
    // TODO: How do we handle this?
    return;
  }

  event_queue.ring_buffer[event_queue.write_idx] = *ev;
  event_queue.write_idx = (event_queue.write_idx + 1) % EVENT_QUEUE_SIZE;
}

Event event_pop() {
  if (event_num_pending() == 0) {
    // TODO: How do we handle this?
    Error_Handler();
  }

  Event result = event_queue.ring_buffer[event_queue.read_idx];
  event_queue.read_idx = (event_queue.read_idx + 1) % EVENT_QUEUE_SIZE;
  return result;
}

uint16_t event_num_pending() {
  // Copy the values so we can be sure they don't change while we're computing
  // this
  uint16_t read_idx = event_queue.read_idx;
  uint16_t write_idx = event_queue.write_idx;
  if (write_idx >= read_idx) {
    return write_idx - read_idx;
  } else {
    return write_idx + (EVENT_QUEUE_SIZE - read_idx);
  }
}

uint16_t event_num_free() {
  // Copy the values so we can be sure they don't change while we're computing
  // this
  uint16_t read_idx = event_queue.read_idx;
  uint16_t write_idx = event_queue.write_idx;
  if (read_idx > write_idx) {
    return read_idx - write_idx;
  } else {
    return read_idx + (EVENT_QUEUE_SIZE - write_idx);
  }
}

void handle_events() {
  while (event_num_pending() > 0) {
    Event ev = event_pop();
    switch (ev.type) {
    case EV_BTN_PRESS:
      handle_button_press(&ev.btn_press);
      break;
    default:
      Error_Handler();
    }
  }
}