#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "labcomm_fd_reader.h"

#define BUFFER_SIZE 2048

int labcomm_fd_reader(
  labcomm_reader_t *r, 
  labcomm_reader_action_t action,
  ...)
{
  int result = -EINVAL;
  int *fd = r->context;
  
  switch (action) {
    case labcomm_reader_alloc: {
#ifndef LABCOMM_FD_OMIT_VERSION
      va_list ap;
      va_start(ap, action);
      char *version = va_arg(ap, char *);
      char *tmp = strdup(version);

      read(*fd, tmp, strlen(version));
      free(tmp);
#endif
      r->data = malloc(BUFFER_SIZE);
      if (r->data) {
        r->data_size = BUFFER_SIZE;
        result = r->data_size;
      } else {
        r->data_size = 0;
        result = -ENOMEM;
      }
      r->count = 0;
      r->pos = 0;
#ifndef LABCOMM_FD_OMIT_VERSION
	va_end(ap);
#endif
    } break;
    case labcomm_reader_start: 
    case labcomm_reader_continue: {
      if (r->pos < r->count) {
        result = r->count - r->pos;
      } else {
        int err;

        r->pos = 0;
        err = read(*fd, r->data, r->data_size);
        if (err <= 0) {
          r->count = 0;
          result = -1;
        } else {
          r->count = err;
          result = r->count - r->pos;
        }
      }
    } break;
    case labcomm_reader_end: {
      result = 0;
    } break;
    case labcomm_reader_free: {
      free(r->data);
      r->data = 0;
      r->data_size = 0;
      r->count = 0;
      r->pos = 0;
      result = 0;
    } break;
    case labcomm_reader_ioctl: {
      result = -ENOTSUP;
    }
  }
  return result;
}