////////////////////////////////////////////////////////
// RemoteLog
//
// This implements RemoteLogIF
//
// It acts a simple UDP message broadcaster to get 
// write information to the topside module
//
///////////////////////////////////////////////////////

#include "RemoteLog.h"

#include <ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>

#include <arpa/inet.h>
#include <net/if.h>

#include "Time.h"
#include "Syslog.h"

#define PORT_NUM 2390
#define DEFAULT_DEBUG 5

RemoteLog::RemoteLog()
    : RemoteLogIF_SK()
{

    //setting default debug level
    _debugLevel = DEFAULT_DEBUG;

    if ((_sockNum = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
	Syslog::write("RemoteLog -- Error creating socket. Exiting...");
	exit (1);
    }
    int on = 1;
    if (ioctl(_sockNum, FIONBIO, &on) < 0) {
        Syslog::write("RemoteLog -- Error setting non-blocking. Exiting...");
        exit(1);
    }
    
    on = 1;
    if ((setsockopt(_sockNum, SOL_SOCKET, SO_BROADCAST, (void *)&on, sizeof (on))) != 0) {
	Syslog::write("Remote Log -- Error setting broadcast. Exiting...");
	exit (1);
    }
    
    unsigned long zeroSub;
    zeroSub = inet_addr("192.168.0.255");

    sinZero.sin_family = AF_INET;
    //sin.sin_addr.s_addr = htonl(zeroSub);
    sinZero.sin_addr.s_addr = zeroSub;
    sinZero.sin_port = htons(PORT_NUM);
    
    unsigned long oneSub;
    oneSub = inet_addr("192.168.1.255");

    sinOne.sin_family = AF_INET;
    //sin.sin_addr.s_addr = htonl(oneSub);
    sinOne.sin_addr.s_addr = oneSub;
    sinOne.sin_port = htons(PORT_NUM);
}

RemoteLog::~RemoteLog()
{
}

void RemoteLog::remoteWrite(short debug, RemoteLogIF::MessageString mes)
{
    char* form;
    int size;
   
    //malloc occurs in the function
    form = formatString(mes, debug, &size);

    //fprintf(stdout, "Actual message = %s\n", form);

    //fprintf(stdout, "DebugLevel: %d debug: %d\n", _debugLevel, debug);

    if(debug <= _debugLevel) {
	Syslog::write("RemoteLog -- sending message << %s >>", mes);
	if ( (errno = sendto(_sockNum, form, size, 0, (struct sockaddr *)&sinZero, sizeof(struct sockaddr))) == -1) {
	    fprintf(stderr,"Error sending zero packet: %d\n",errno);
	    //exit(1);
	}
	//TODO - muck with freewave
	/*
	  if ( (errno = sendto(_sockNum, form, size, 0, (struct sockaddr *)&sinOne, sizeof(struct sockaddr))) == -1) {
	  fprintf(stderr,"Error sending one packet: %d\n",errno);
	  //exit(1);
	  }
	*/
    }

    free(form);
}

char* RemoteLog::formatString(RemoteLogIF::MessageString mes, short debug, int* size) 
{
    char* hold;
    //would be a lot of trouble to do this right
    //you'd need to send info on how big things were
    //or just write stuff out as characters
    //but you can't really use binary data and delimeters
    //so I'm just gonna hard code this for now
    // 2B id + 2B short size + 1B debug + 8B time
    unsigned short headerSize = 13;
    unsigned short dataSize = strlen(mes);
    unsigned short totSize = dataSize+headerSize;
    //fprintf(stdout, "Time: %12.4lf\n", Time::secondsNow(false));
    time_t t = time(NULL);
    double dt = Time::secondsNow(false);
  
    hold = (char *)malloc(sizeof(char)*totSize);

    memset(hold, 0, totSize);
    
    hold[0] = '@';
    hold[1] = '$';
    memcpy(&(hold[2]), &dataSize, sizeof(unsigned short));
    hold[4] = (char) debug;
    memcpy(&(hold[5]), &dt, sizeof(double));
    strncpy(&(hold[headerSize]), mes, dataSize);

    *size = totSize;
    return hold;
}
