# include <kapa_internal.h>

/* why is this not defined in stdarg.h for linux/x64? */
int vsscanf(const char *str, const char *format, va_list ap);

int KiiSendData (int device, char *data, int Nbytes) {

  KiiSendCommand (device, 16, "LEN: %11d", Nbytes);
  write (device, data, Nbytes);
  return (TRUE);
} 

char *KiiRecvData (int device) {

  int status, Nbytes;
  char *data, buffer[20];

  /* read 16 bytes: LEN (length) */
  status = read (device, buffer, 16);
  buffer[16] = 0;

  /* find the message length, allocate space */
  sscanf (buffer, "%*s %d", &Nbytes);
  ALLOCATE (data, char, Nbytes + 1);
  read (device, data, Nbytes);
  data[Nbytes] = 0;

  return (data);
} 

/* send a message of arbitrary size, sending the size first */
int KiiSendMessage (int device, char *format, ...) {

  int Nbyte, status;
  char tmp;
  va_list argp;  

  va_start (argp, format);
  Nbyte = vsnprintf (&tmp, 0, format, argp);
  va_end (argp);

  if (!Nbyte) return (FALSE);

  /* the message may contain up to 99,999,999,999 bytes (100MB) */
  va_start (argp, format);
  KiiSendCommand (device, 16, "LEN: %11d", Nbyte);
  status = KiiSendCommandV (device, Nbyte, format, argp);
  va_end (argp);

  return (status);
}

int KiiSendCommand (int device, int length, char *format, ...) {

  int status;
  va_list argp;  

  va_start (argp, format);
  status = KiiSendCommandV (device, length, format, argp);
  va_end (argp);

  return (status);
}
  
int KiiSendCommandV (int device, int length, char *format, va_list argp) {

  char *string;

  /* string is sent WITHOUT ending NULL char */
  /* allocate and zero length + 1 extra byte */
  ALLOCATE (string, char, length + 1);
  memset (string, 0, length + 1);
  vsnprintf (string, length + 1, format, argp);

  write (device, string, length);
  free (string);
  return (TRUE);
}

/* scan a message of arbitrary size, accepting the size first */
int KiiScanMessage (int device, char *format, ...) {

  int Nbytes, status;
  char buffer[20], *message;
  va_list argp;  

  /* read 16 bytes: LEN (length) */
  status = read (device, buffer, 16);
  buffer[16] = 0;

  /* find the message length, allocate space */
  sscanf (buffer, "%*s %d", &Nbytes);
  ALLOCATE (message, char, Nbytes + 1);

  /* read Nbytes from the device */
  status = read (device, message, Nbytes);
  if (status != Nbytes) fprintf (stderr, "Kii/Kapa comm error\n");
  message[status] = 0;
  /* make the string easy to parse */

  /* scan the incoming message */
  va_start (argp, format);
  Nbytes = vsscanf (message, format, argp);
  va_end (argp);

  return (status);
}
