#include "rpi_cava.h"

#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

pid_t cavaPid;
pthread_t fifoReader;
int cavaFifo;
uint16_t buffer[20];

static void *fifo_to_buffer(void *arg);

void setup_cava() {}

void close_cava() { cava_stop(); }

void cava_start() {
  if ((cavaPid = fork()) == -1) {
    perror("fork");
    exit(1);
  }

  if (cavaPid == 0) {
    /* Child process*/
    char *args[] = {"/usr/local/bin/cava", "-p", "/home/pi/LedBars/RpiLedBars/cava_config", NULL};

    if (execv(args[0], args) != 0) {
      perror("execv");
    }

  } else {

    sleep(1);
    if ((cavaFifo = open("/tmp/cava_output", O_RDONLY)) < 0) {
      perror("open");
      close_cava();
      exit(1);
    }

    pthread_create(&fifoReader, NULL, fifo_to_buffer, NULL);
  }
}

void cava_stop() {
  if (pthread_cancel(fifoReader) != 0) {
    perror("pthread_cancel");
  }
  if (pthread_join(fifoReader, NULL) != 0) {
    perror("pthread_join");
  }
  close(cavaFifo);
  kill(cavaPid, SIGTERM);
}

int get_cava_buffer(uint16_t buffer_dst[20]) {
  memcpy(buffer_dst, buffer, 40);
  return 0;
}

static void *fifo_to_buffer(void *arg) {
  while (1) {
    int totalRead = 0;
    while (totalRead < 40) {
      int nread;
      nread = read(cavaFifo, ((uint8_t *)buffer) + totalRead, 40 - totalRead);
      if (nread >= 0) {
        totalRead += nread;
      } else {
        if (errno != EAGAIN) {
          perror("read");
        }
      }
    }

    printf("data[%d] : ", totalRead);
    for (size_t i = 0; i < 20; i++) {
      printf("%5u;", buffer[i]);
    }
    printf("\n");
  }
  return NULL;
}
