#ifndef __handlers_h__
#define __handlers_h__

#include "lcmtypes/senlcm_os_compass_t.h"
#include "lcmtypes/senlcm_kvh_dsp3000_t.h"
#include "lcmtypes/senlcm_dstar_ssp1_t.h"
#include "lcmtypes/senlcm_rdi_pd4_t.h"
#include "lcmtypes/senlcm_ms_gx1_t.h"
#include "lcmtypes/senlcm_ppsboard_t.h"
#include "lcmtypes/senlcm_gpsd_t.h"

#include "textread.h"

#ifdef __cplusplus
extern "C" {
#endif

void
senlcm_os_compass_t_handler (const lcm_recv_buf_t *rbuf, const char *channel, 
                             const senlcm_os_compass_t *msg, void *user)
{
    textread_t *tr = user;

    textread_start (tr, channel);

    textread_add_field (tr, "utime",    "%"PRId64, msg->utime);
    textread_add_field (tr, "rph(:,1)", "%f",      msg->rph[0]);
    textread_add_field (tr, "rph(:,2)", "%f",      msg->rph[1]);
    textread_add_field (tr, "rph(:,3)", "%f",      msg->rph[2]);
    textread_add_field (tr, "T",        "%f",      msg->T);
    textread_add_field (tr, "depth",    "%f",      msg->depth);
    textread_add_field (tr, "p_volts",  "%f",      msg->p_volts);
    textread_add_field (tr, "p_meas",   "%f",      msg->p_meas);
    textread_add_field (tr, "p_gage",   "%f",      msg->p_gage);
    textread_add_field (tr, "p_o",      "%f",      msg->p_o);
    textread_add_field (tr, "Mxyz(:,1)","%f",      msg->Mxyz[0]);
    textread_add_field (tr, "Mxyz(:,2)","%f",      msg->Mxyz[1]);
    textread_add_field (tr, "Mxyz(:,3)","%f",      msg->Mxyz[2]);
    textread_add_field (tr, "Gxyz(:,1)","%f",      msg->Gxyz[0]);
    textread_add_field (tr, "Gxyz(:,2)","%f",      msg->Gxyz[1]);
    textread_add_field (tr, "Gxyz(:,3)","%f",      msg->Gxyz[2]);

    textread_stop (tr);
}

void 
senlcm_kvh_dsp3000_t_handler (const lcm_recv_buf_t *rbuf, const char * channel, 
        		      const senlcm_kvh_dsp3000_t * msg, void * user)
{
    textread_t *tr = user;

    textread_start (tr, channel);

    textread_add_field (tr, "utime",    "%"PRId64, msg->utime);
    textread_add_field (tr, "mode",     "%"PRId8,  msg->mode);
    textread_add_field (tr, "data",     "%f",      msg->data);

    textread_add_const (tr, "RATE_MODE", SENLCM_KVH_DSP3000_T_RATE_MODE);
    textread_add_const (tr, "DELTA_MODE", SENLCM_KVH_DSP3000_T_DELTA_MODE);
    textread_add_const (tr, "ANGLE_MODE", SENLCM_KVH_DSP3000_T_ANGLE_MODE);
    textread_stop (tr);
}
		
void 
senlcm_dstar_ssp1_t_handler (const lcm_recv_buf_t *rbuf, const char * channel, 
                              const senlcm_dstar_ssp1_t * msg, void * user)
{
    textread_t *tr = user;

    textread_start (tr, channel);

    textread_add_field (tr, "utime",      "%"PRId64,msg->utime);
    textread_add_field (tr, "p_abs",      "%f",     msg->p_abs);
    textread_add_field (tr, "p_gage",     "%f",     msg->p_gage);
    textread_add_field (tr, "p_atm",      "%f",     msg->p_atm);
    textread_add_field (tr, "depth",      "%f",     msg->depth);
    textread_add_field (tr, "temperature","%f",     msg->temperature);

    textread_stop (tr);
		
}		
		
void
senlcm_rdi_pd4_t_handler (const lcm_recv_buf_t *rbuf, const char * channel, 
        const senlcm_rdi_pd4_t * msg, void * user)
{
    textread_t *tr = user;

    textread_start (tr, channel);

    textread_add_field (tr, "utime",            "%"PRId64, msg->utime);
    textread_add_field (tr, "system_config",    "%"PRIu8,  msg->system_config);
    textread_add_field (tr, "btv(:,1)",         "%f",      msg->btv[0]);
    textread_add_field (tr, "btv(:,2)",         "%f",      msg->btv[1]);
    textread_add_field (tr, "btv(:,3)",         "%f",      msg->btv[2]);
    textread_add_field (tr, "btv(:,4)",         "%f",      msg->btv[3]);
    textread_add_field (tr, "btv_status",       "%"PRIu8,  msg->btv_status);
    textread_add_field (tr, "wtv(:,1)",         "%f",      msg->wtv[0]);
    textread_add_field (tr, "wtv(:,2)",         "%f",      msg->wtv[1]);
    textread_add_field (tr, "wtv(:,3)",         "%f",      msg->wtv[2]);
    textread_add_field (tr, "wtv(:,4)",         "%f",      msg->wtv[3]);
    textread_add_field (tr, "wtv_status",       "%"PRIu8,  msg->wtv_status);
    textread_add_field (tr, "wtv_layer_start",  "%f",      msg->wtv_layer_start);
    textread_add_field (tr, "wtv_layer_end",    "%f",      msg->wtv_layer_end);
    textread_add_field (tr, "range(:,1)",       "%f",      msg->range[0]);
    textread_add_field (tr, "range(:,2)",       "%f",      msg->range[1]);
    textread_add_field (tr, "range(:,3)",       "%f",  msg->range[2]);
    textread_add_field (tr, "range(:,4)",       "%f",      msg->range[3]);
    textread_add_field (tr, "altitude",         "%f",      msg->altitude);
    textread_add_field (tr, "tofp_hour",        "%"PRIu8,  msg->tofp_hour);
    textread_add_field (tr, "tofp_minute",      "%"PRIu8,  msg->tofp_minute);
    textread_add_field (tr, "tofp_second",      "%"PRIu8,  msg->tofp_second);
    textread_add_field (tr, "tofp_hundredth",   "%"PRIu8,  msg->tofp_hundredth);
    textread_add_field (tr, "builtin_test(:,1)","%"PRIu8,  msg->builtin_test[0]);
    textread_add_field (tr, "builtin_test(:,2)","%"PRIu8,  msg->builtin_test[1]);
    textread_add_field (tr, "speed_of_sound",   "%f",      msg->speed_of_sound);
    textread_add_field (tr, "xducer_head_temp", "%f",      msg->xducer_head_temp);

    textread_add_const (tr, "BAD_VELOCITY", SENLCM_RDI_PD4_T_BAD_VELOCITY);
    textread_stop (tr);
}
    
void 
senlcm_ms_gx1_t_handler (const lcm_recv_buf_t *rbuf, const char * channel, 
                const senlcm_ms_gx1_t * msg, void * user)
{
    textread_t *tr = user;

    textread_start (tr, channel);

    // fields
    textread_add_field (tr, "utime",          "%"PRId64,  msg->utime);
    textread_add_field (tr, "bitmask",        "%"PRId64,  msg->bitmask);
    textread_add_field (tr, "sMagField(:,1)", "%f",       msg->sMagField[0]);
    textread_add_field (tr, "sMagField(:,2)", "%f",       msg->sMagField[1]);
    textread_add_field (tr, "sMagField(:,3)", "%f", 	  msg->sMagField[2]);
    textread_add_field (tr, "sAccel(:,1)",    "%f",	  msg->sAccel[0]);
    textread_add_field (tr, "sAccel(:,2)",    "%f",	  msg->sAccel[1]);
    textread_add_field (tr, "sAccel(:,3)",    "%f",	  msg->sAccel[2]);
    textread_add_field (tr, "sAngRate(:,1)",  "%f",	  msg->sAngRate[0]);
    textread_add_field (tr, "sAngRate(:,2)",  "%f",	  msg->sAngRate[1]);
    textread_add_field (tr, "sAngRate(:,3)",  "%f",	  msg->sAngRate[2]);
    textread_add_field (tr, "sEuler(:,1)",    "%f",	  msg->sEuler[0]);
    textread_add_field (tr, "sEuler(:,2)",    "%f",       msg->sEuler[1]);
    textread_add_field (tr, "sEuler(:,3)",    "%f",	  msg->sEuler[2]);
    textread_add_field (tr, "sM1(:,1)",       "%f",	  msg->sM[0][0]);
    textread_add_field (tr, "sM1(:,2)",       "%f",	  msg->sM[0][1]);
    textread_add_field (tr, "sM1(:,3)",       "%f",	  msg->sM[0][2]);
    textread_add_field (tr, "sM2(:,1)",       "%f",	  msg->sM[1][0]);
    textread_add_field (tr, "sM2(:,2)",       "%f",	  msg->sM[1][1]);
    textread_add_field (tr, "sM2(:,3)",       "%f",	  msg->sM[1][2]);
    textread_add_field (tr, "sM3(:,1)",       "%f",       msg->sM[2][0]);
    textread_add_field (tr, "sM3(:,2)",       "%f",	  msg->sM[2][1]);
    textread_add_field (tr, "sM3(:,3)",       "%f",	  msg->sM[2][2]);
    textread_add_field (tr, "sQ(:,1)",        "%f", 	  msg->sQ[0]);
    textread_add_field (tr, "sQ(:,2)",        "%f",	  msg->sQ[1]);
    textread_add_field (tr, "sQ(:,3)",        "%f",	  msg->sQ[2]);
    textread_add_field (tr, "sQ(:,4)",        "%f",	  msg->sQ[3]);
    textread_add_field (tr, "iMagField(:,1)", "%f",	  msg->iMagField[0]);
    textread_add_field (tr, "iMagField(:,2)", "%f",	  msg->iMagField[1]);
    textread_add_field (tr, "iMagField(:,3)", "%f",	  msg->iMagField[2]);
    textread_add_field (tr, "iAccel(:,1)",    "%f", 	  msg->iAccel[0]);
    textread_add_field (tr, "iAccel(:,2)",    "%f",	  msg->iAccel[1]);
    textread_add_field (tr, "iAccel(:,3)",    "%f",	  msg->iAccel[2]);
    textread_add_field (tr, "iAngRate(:,1)",  "%f", 	  msg->iAngRate[0]);
    textread_add_field (tr, "iAngRate(:,2)",  "%f", 	  msg->iAngRate[1]);
    textread_add_field (tr, "iAngRate(:,3)",  "%f",	  msg->iAngRate[2]);
    textread_add_field (tr, "iEuler(:,1)",    "%f",	  msg->iEuler[0]);
    textread_add_field (tr, "iEuler(:,2)",    "%f",	  msg->iEuler[1]);
    textread_add_field (tr, "iEuler(:,3)",    "%f",	  msg->iEuler[2]);
    textread_add_field (tr, "iM1(:,1)",       "%f",	  msg->iM[0][0]);
    textread_add_field (tr, "iM1(:,2)",       "%f",	  msg->iM[0][1]);
    textread_add_field (tr, "iM1(:,3)",       "%f",	  msg->iM[0][2]);
    textread_add_field (tr, "iM2(:,1)",       "%f",	  msg->iM[1][0]);
    textread_add_field (tr, "iM2(:,2)",       "%f",	  msg->iM[1][1]);
    textread_add_field (tr, "iM2(:,3)",       "%f",	  msg->iM[1][2]);
    textread_add_field (tr, "iM3(:,1)",       "%f",	  msg->iM[2][0]);
    textread_add_field (tr, "iM3(:,2)",       "%f",	  msg->iM[2][1]);
    textread_add_field (tr, "iM3(:,3)",       "%f", 	  msg->iM[2][2]);
    textread_add_field (tr, "iQ(:,1)",        "%f",	  msg->iQ[0]);
    textread_add_field (tr, "iQ(:,2)",        "%f",	  msg->iQ[1]);
    textread_add_field (tr, "iQ(:,3)",        "%f",	  msg->iQ[2]);
    textread_add_field (tr, "iQ(:,4)",        "%f",	  msg->iQ[3]);
    textread_add_field (tr, "Temperature",    "%f",	  msg->Temperature);
    textread_add_field (tr, "TimerTicks",     "%"PRId16,  msg->TimerTicks);

    // constants
    textread_add_const (tr, "INST_MAGFIELD", SENLCM_MS_GX1_T_INST_MAGFIELD);
    textread_add_const (tr, "INST_ACCEL", SENLCM_MS_GX1_T_INST_ACCEL);
    textread_add_const (tr, "INST_ANGRATE", SENLCM_MS_GX1_T_INST_ANGRATE);
    textread_add_const (tr, "INST_EULER", SENLCM_MS_GX1_T_INST_EULER);
    textread_add_const (tr, "INST_M", SENLCM_MS_GX1_T_INST_M);
    textread_add_const (tr, "INST_Q", SENLCM_MS_GX1_T_INST_Q);
    textread_add_const (tr, "STAB_MAGFIELD", SENLCM_MS_GX1_T_STAB_MAGFIELD);
    textread_add_const (tr, "STAB_ACCEL", SENLCM_MS_GX1_T_STAB_ACCEL);
    textread_add_const (tr, "STAB_ANGRATE", SENLCM_MS_GX1_T_STAB_ANGRATE);
    textread_add_const (tr, "STAB_EULER", SENLCM_MS_GX1_T_STAB_EULER);
    textread_add_const (tr, "STAB_M", SENLCM_MS_GX1_T_STAB_M);
    textread_add_const (tr, "STAB_Q", SENLCM_MS_GX1_T_STAB_Q);
    textread_add_const (tr, "TEMPERATURE", SENLCM_MS_GX1_T_TEMPERATURE);

    textread_stop (tr);
}

void 
senlcm_ppsboard_t_handler (const lcm_recv_buf_t *rbuf, const char * channel, 
        		  const senlcm_ppsboard_t * msg, void * user)
{
    textread_t *tr = user;

    textread_start (tr, channel);

    textread_add_field (tr, "utime",        "%"PRId64, msg->utime);
    textread_add_field (tr, "ntp_time",     "%s",      msg->ntp_time)
    textread_add_field (tr, "ntp_status",   "%"PRId8,  msg->ntp_status);
    textread_add_field (tr, "src_type",     "%s",      msg->src_type);
    textread_add_field (tr, "src_pps",      "%"PRId8,  msg->src_pps);
    textread_add_field (tr, "sync_mode",    "%"PRId16, msg->sync_mode);
    textread_add_field (tr, "sync_num",     "%"PRId16, msg->sync_num);
    textread_add_field (tr, "sync_date",    "%s",      msg->sync_date);
    textread_add_field (tr, "sync_time",    "%s",      msg->sync_time);
    textread_add_field (tr, "offset",       "%"PRId16, msg->offset_counts);
    textread_add_field (tr, "offset_usecs", "%f",      msg->offset_usecs);
    textread_add_field (tr, "temperature",  "%f",      msg->temperature);

    textread_stop (tr);
}

void 
senlcm_gpsd_t_handler (const lcm_recv_buf_t *rbuf, const char * channel, 
              	       const senlcm_gpsd_t * msg, void * user)
{
    textread_t *tr = user;

    textread_start (tr, channel);

    textread_add_field (tr, "utime",            "%"PRId64, 	msg->utime);
    textread_add_field (tr, "online", 		"%"PRId64,	msg->online);
    textread_add_field (tr, "fix_utime", 	"%"PRId64,	msg->fix_utime);
    textread_add_field (tr, "mode",		"%"PRId8,	msg->mode);
    textread_add_field (tr, "ept",		"%f",		msg->ept);
    textread_add_field (tr, "latitude",		"%f",		msg->latitude);
    textread_add_field (tr, "longitude",        "%f",           msg->longitude);
    textread_add_field (tr, "altitude",		"%f",		msg->altitude);
    textread_add_field (tr, "eph",		"%f",		msg->eph);
    textread_add_field (tr, "epv",		"%f",		msg->epv);
    textread_add_field (tr, "track",		"%f",		msg->track);
    textread_add_field (tr, "epd",		"%f",		msg->epd);
    textread_add_field (tr, "speed",		"%f",		msg->speed);
    textread_add_field (tr, "eps",		"%f",		msg->eps);
    textread_add_field (tr, "climb",		"%f",		msg->climb);
    textread_add_field (tr, "epc",		"%f",		msg->epc);
    textread_add_field (tr, "geoidal_separation","%f",		msg->geoidal_separation);
    textread_add_field (tr, "status",		"%"PRId16,	msg->status);
    textread_add_field (tr, "satellites_used",	"%"PRId16,	msg->satellites_used);

    for(int i_used=0;i_used<12;i_used++) {
	char buf[20];
	snprintf (buf, sizeof buf, "used(:,%d)", i_used+1);
    	textread_add_field (tr, buf, "%"PRId16, i_used < msg->satellites_used ? msg->used[i_used] : 0);
    }
    
    textread_add_field (tr, "pdop",		  "%f",         msg->pdop);
    textread_add_field (tr, "hdop",		  "%f",         msg->hdop);
    textread_add_field (tr, "tdop",		  "%f",         msg->tdop);
    textread_add_field (tr, "gdop",		  "%f",         msg->gdop);
    textread_add_field (tr, "epe",		  "%f",         msg->epe);
    textread_add_field (tr, "satellites_visible", "%"PRId16,    msg->satellites_visible);
    
    for(int i_PRN=0;i_PRN<12;i_PRN++) {
	char buf[20];
	snprintf (buf, sizeof buf, "PRN(:,%d)", i_PRN+1);
    	textread_add_field (tr, buf, "%"PRId16, i_PRN < msg->satellites_visible ? msg->PRN[i_PRN] : 0);
    }

    for(int i_elevation=0;i_elevation<12;i_elevation++) {
	char buf[20];
	snprintf (buf, sizeof buf, "elevation(:,%d)", i_elevation+1);
    	textread_add_field (tr, buf, "%"PRId16,	i_elevation < msg->satellites_visible ? msg->elevation[i_elevation] : 0);
    }
    
    for(int i_azimuth=0;i_azimuth<12;i_azimuth++) {
	char buf[20];
	snprintf (buf, sizeof buf, "azimuth(:,%d)", i_azimuth+1);
    	textread_add_field (tr, buf, "%"PRId16,	i_azimuth < msg->satellites_visible ? msg->azimuth[i_azimuth] : 0);
    }

    for(int i_ss=0;i_ss<12;i_ss++) {
	char buf[20];
	snprintf (buf, sizeof buf, "ss(:,%d)", i_ss+1);
    	textread_add_field (tr, buf, "%"PRId16, i_ss < msg->satellites_visible ? msg->ss[i_ss] : 0);
    }
    
    textread_add_field (tr, "gps_device",	"%s",	 	msg->gps_device);
    textread_add_field (tr, "gps_id",		"%s",		msg->gps_id);
    textread_add_field (tr, "ndevices",  	"%"PRId16,	msg->ndevices);
    textread_add_field (tr, "devicelist(:,1)",	"%s",		msg->devicelist[0]);
    textread_add_field (tr, "devicelist(:,2)",	"%s",		msg->devicelist[1]);

    textread_add_const (tr, "MODE_NOT_SEEN", SENLCM_GPSD_T_MODE_NOT_SEEN);
    textread_add_const (tr, "MODE_NO_FIX", SENLCM_GPSD_T_MODE_NO_FIX);
    textread_add_const (tr, "MODE_2D", SENLCM_GPSD_T_MODE_2D);
    textread_add_const (tr, "MODE_3D", SENLCM_GPSD_T_MODE_3D);
    textread_add_const (tr, "STATUS_NO_FIX", SENLCM_GPSD_T_STATUS_NO_FIX);
    textread_add_const (tr, "STATUS_FIX", SENLCM_GPSD_T_STATUS_FIX);
    textread_add_const (tr, "STATUS_DGPS_FIX", SENLCM_GPSD_T_STATUS_DGPS_FIX);
    textread_stop (tr);
}
#ifdef __cplusplus
}
#endif

#endif //__handlers_h__
