#include "batch_ipc.h"


/* Message buffer */
static char msgBuf[MAX_BUFF_LEN];


static int sendMsg(const char* msg){
	fprintf(stdout,"%s\n", msgBuf);	
return 0;
}

static int rcvMsg(char* msg){
  int bufLen;

	fgets(msg, MAX_BUFF_LEN, stdin);

	if( feof(stdin) )
		return E_END;

	bufLen = strlen(msg);
	/* Get rid of possible eol */
	if( msg[bufLen-1] == '\n' )
		msg[bufLen-1] = 0;
return 0;
}


static int buildMsg(char* msg, const WifiPair* pair){

	sprintf(msgBuf,"%X %02X:%02X:%02X:%02X:%02X:%02X %f %f %f %hu %02X:%02X:%02X:%02X:%02X:%02X %f %f %f %hu %i %f %hu %f %f %hu %f %f %hu %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f" ,
		pair->type, 
		pair->tx.mac.str[0],
		pair->tx.mac.str[1],
		pair->tx.mac.str[2],
		pair->tx.mac.str[3],
		pair->tx.mac.str[4],
		pair->tx.mac.str[5],
		pair->tx.X,
		pair->tx.Y,
		pair->tx.Z,
		pair->tx.Gain,
		pair->rx.mac.str[0],
                pair->rx.mac.str[1],
                pair->rx.mac.str[2],
                pair->rx.mac.str[3],
                pair->rx.mac.str[4],
                pair->rx.mac.str[5],
                pair->rx.X,
                pair->rx.Y,
                pair->rx.Z,
                pair->rx.Gain,
		pair->time,
		pair->S,
		pair->numS,
		pair->sigmaS,
		pair->R,
		pair->numR,
		pair->sigmaR,
		pair->Rcalc,
		pair->numRcalc,
		pair->sigmaRcalc,
		pair->sigmaRproj,
		pair->nPow,
		pair->sigmaN,
		pair->nS0,
		pair->sigmaNS0,
		pair->kPow,
		pair->sigmaK,
		pair->kS0,
		pair->sigmaKS0,
		pair->C2,
		pair->sigmaC2,
		pair->C1,
		pair->sigmaC1,
		pair->C0,
		pair->sigmaC0
		);
return 0;
}

static int parseMsg(const char* msg, WifiPair* pair){

	if(*msgBuf=='#' || *msgBuf==0)
		return 1;

	sscanf(msgBuf,"%X %02X:%02X:%02X:%02X:%02X:%02X %f %f %f %hu %02X:%02X:%02X:%02X:%02X:%02X %f %f %f %hu %i %f %hu %f %f %hu %f %f %hu %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",
	       &pair->type, 
	       &pair->tx.mac.str[0],
	       &pair->tx.mac.str[1],
	       &pair->tx.mac.str[2],
	       &pair->tx.mac.str[3],
	       &pair->tx.mac.str[4],
	       &pair->tx.mac.str[5],
	       &pair->tx.X,
	       &pair->tx.Y,
	       &pair->tx.Z,
	       &pair->tx.Gain,
	       &pair->rx.mac.str[0],
	       &pair->rx.mac.str[1],
	       &pair->rx.mac.str[2],
	       &pair->rx.mac.str[3],
	       &pair->rx.mac.str[4],
	       &pair->rx.mac.str[5],
	       &pair->rx.X,
	       &pair->rx.Y,
	       &pair->rx.Z,
	       &pair->rx.Gain,
	       &pair->time,
	       &pair->S,
	       &pair->numS,
	       &pair->sigmaS,
	       &pair->R,
	       &pair->numR,
	       &pair->sigmaR,
	       &pair->Rcalc,
	       &pair->numRcalc,
	       &pair->sigmaRcalc,
	       &pair->sigmaRproj,
	       &pair->nPow,
	       &pair->sigmaN,
	       &pair->nS0,
	       &pair->sigmaNS0,
	       &pair->kPow,
	       &pair->sigmaK,
	       &pair->kS0,
	       &pair->sigmaKS0,
	       &pair->C2,
	       &pair->sigmaC2,
	       &pair->C1,
	       &pair->sigmaC1,
	       &pair->C0,
	       &pair->sigmaC0);

	if( pair->type & (C_RXYZ | C_TXYZ) ){
	  pair->R = sqrt( (pair->rx.X-pair->tx.X)*(pair->rx.X-pair->tx.X) +
			  (pair->rx.Y-pair->tx.Y)*(pair->rx.Y-pair->tx.Y) +
			  (pair->rx.Z-pair->tx.Z)*(pair->rx.X-pair->tx.Z) );
	  pair->type |= C_RADIUS;
	}

return 0;
}


void outputResult(int sig){
int stat;
Iterator it;
WifiPair* pair;

	/* Save current records */
	if( (stat=getFirstHash(&curWifi, &it)) ){
		if( stat != E_END )
			exit(1);
	}else
	while(1){
	
		pair = (WifiPair*) it.ptr;

		buildMsg(msgBuf, pair);
		sendMsg(msgBuf);

		if( (stat = getNextHash(&curWifi, &it)) )
			if( stat != E_END )
				exit(1);
			else
				break;
	};

	/* Save calibrated records */
	if( (stat=getFirstHash(&clbrWifi, &it)) ){
		if( stat != E_END )
			exit(1);
	}else
	while(1){
	
		pair = (WifiPair*) it.ptr;
		
		buildMsg(msgBuf, pair);
		sendMsg(msgBuf);

		if( (stat = getNextHash(&clbrWifi, &it)) )
			if( stat != E_END )
				exit(1);
			else
				break;
	};

exit(0);
}


int initLoad(){
int stat;
WifiPair pair;	

	while( !(stat = rcvMsg(msgBuf)) ){
	  /* if this message is not valid - no problem - read next one */
	  if( !parseMsg(msgBuf, &pair) ){
	    if( pair.type & C_SIGNAL && 
		(pair.type & C_RXYZ || pair.type & C_TXYZ || pair.type & C_RADIUS) )
	      stat = upsertHash(&clbrWifi, &pair);	 
	    else
	      stat = upsertHash(&curWifi, &pair);	 

	    if(stat)
	      return stat;
	  }
	}

	if( stat != E_END )
		return stat;

return 0;
}


