#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include "lineIOServ.h"

int readLine(int sio, char *lineBuff, int lineSize,
	     struct timeval *timeLimit ) {
  int lineRead, rc ;
  struct timeval presTime, alarmTime, selLimit ;
  fd_set sioOn ;

  /* Set the alarm clock */
  (void) gettimeofday(&presTime, (struct timezone *)NULL) ;
  /* timeradd(&presTime, timeLimit, &alarmTime) ; */
  alarmTime.tv_usec = presTime.tv_usec + timeLimit->tv_usec ;
  alarmTime.tv_sec  = presTime.tv_sec  + timeLimit->tv_sec  ;
  if (alarmTime.tv_usec >= 1000000) {
    alarmTime.tv_usec -= 1000000 ;
    alarmTime.tv_sec++ ;
  }

  /* Set the initial select limit */
  selLimit = *timeLimit ;

  lineRead = 0 ;
  while ((lineRead < lineSize) &&
	 ((lineRead<2) || (lineBuff[lineRead-2] != '\r') ||
          (lineBuff[lineRead-1] != '\n'))) {
    FD_ZERO(&sioOn) ;
    FD_SET(sio, &sioOn) ;
    if (select(sio+1, &sioOn, (fd_set *)NULL, (fd_set *)NULL, &selLimit)) {
      rc = read(sio, &lineBuff[lineRead], lineSize-lineRead) ;
      if (rc <= 0)
	return -1 ;
      lineRead += rc ;
      /* Recompute the time limit */
      (void) gettimeofday(&presTime, (struct timezone *)NULL) ;
      /* timersub(&alarmTime, &presTime, &selLimit) ; */
      selLimit.tv_usec = alarmTime.tv_usec - presTime.tv_usec ;
      selLimit.tv_sec  = alarmTime.tv_sec  - presTime.tv_sec  ;
      if (selLimit.tv_usec < 0) {
	selLimit.tv_usec += 1000000 ;
	selLimit.tv_sec-- ;
      }
      if (selLimit.tv_sec < 0)	/* Seems extremely unlikely */
	selLimit.tv_sec = selLimit.tv_usec = 0 ;
    } else
      return -2 ;
  }
  return lineRead ;
}
  

int writeLine(int sio, char *mess, int randLimit) {
  int messLen, messWrit, rc ;
  char outBuff[256] ;
  (void) strcpy(outBuff, mess) ;	/* Must be less than 250 char */
  (void) strcat(outBuff, "\r\n") ;
  messLen =  (int) strlen(outBuff) ;
  messWrit = 0 ;
  while (messWrit < messLen) {
    /* calculate the number to send before waiting a second */
    int numSend = 0 ;
    while (rand() % randLimit)
      ++numSend ;
    if (numSend) {
      if (numSend > messLen-messWrit)
	numSend = messLen-messWrit ;
      rc = write(sio, &outBuff[messWrit], numSend) ;
      if (rc <= 0)
	return -1 ;
      messWrit += rc ;
      if (messWrit < messLen)
	sleep(1) ;
    } else {
      (void) sleep(1) ;
    }
  }
  return messWrit ;
}
