/**---------------------------------------------------------------------------
 ** 
 ** scan.c -- Navigation scanning utilities 
 ** 
 ** Author          : Pierre Jaccard
 ** Created On      : 1999/07/15 15:08:41
 ** Last Modified By: Pierre Jaccard
 ** Last Modified On: 1999/09/21 14:27:45
 ** Update Count    : 11
 ** Directory       : /pcdata1/jaccard/codas3c/gfi/src/libs/nav/
 ** Version         : 0.0
 ** Status          : Unknown
 ** ---------------------------------------------------------------------- ** 
 ** DESCRIPTION: 
 ** 
 **    These functions are used to create a report about navigiation for each
 **    ping. Also provided here are functions to read back these reports.
 ** 
 ** ---------------------------------------------------------------------- ** 
 ** REVISIONS: 
 ** ---------------------------------------------------------------------- ** 
 ** CHANGES: 
 **
 ** 1999/09/03 Pierre Jaccard
 **            Addding support for RMC message
 **------------------------------------------------------------------------**/

#include <stdio.h>
#include "scan.h"

/* ------------------------------------------------------------------
	 This function writes the content of a Scan Nav line structure into a file.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int write_scan_nav_line(/* Output file */
                        FILE *fp, 
                        /* Pointer to navigation data */
                        SCAN_NAV_LINE_TYPE *scan, 
                        /* Year base */
                        int year_base)
#else
int write_scan_nav_line(fp, scan, year_base)
FILE *fp;
ENSEMBLE_TYPE *ens;
#endif
{

	char str[100];

	static BYTE first_pass = 1;
	int good_stat = 0;

	/* Write header */
	if(first_pass){
		first_pass=0;
		fprintf(fp, "%% ***** SCAN_NAV: Data Description ***************\n");
		fprintf(fp, "%%  1 : Ensemble number\n");
		fprintf(fp, "%%  2 : Ensemble start time in YMD HMH format\n");
		fprintf(fp, "%%  4 : Ensemble stop  time in YMD HMH format\n");
		fprintf(fp, "%%  6 : Ensemble start latitude  in D M {N|S} format\n");
		fprintf(fp, "%%  9 : Ensemble start longitude in D M {E|W} format\n");
		fprintf(fp, "%% 12 : Ensemble stop  latitude  in D M {N|S} format\n");
		fprintf(fp, "%% 15 : Ensemble stop  longitude in D M {E|W} format\n");
		fprintf(fp, "%% 18 : Heading: MEAN SDEV  NPTS\n");
		fprintf(fp, "%% 21 : Pitch  : MEAN SDEV  NPTS\n");
		fprintf(fp, "%% 24 : Roll   : MEAN SDEV  NPTS\n");
		fprintf(fp, "%% 27 : Course : MEAN SDEV  NPTS\n");
		fprintf(fp, "%% 30 : Speed  : MEAN SDEV  NPTS\n");
		fprintf(fp, "%% ************************************************\n");
	}

	/* Write ensemble number */
	fprintf(fp, " %5hu ", scan->number);
	
	/* time and position limits */
	yd_to_ymdhms_str(str, scan->time.start, year_base);
	fprintf(fp, "%s  ", str);
	yd_to_ymdhms_str(str, scan->time.stop, year_base);
	fprintf(fp, "%s  ", str);
	degree_to_str(str, scan->pos.start.lat, 1, DM_FORMAT_CODE);
	fprintf(fp, "%s  ", str);
	degree_to_str(str, scan->pos.start.lon, -1, DM_FORMAT_CODE);
	fprintf(fp, "%s  ", str);
	degree_to_str(str, scan->pos.stop.lat, 1, DM_FORMAT_CODE);
	fprintf(fp, "%s  ", str);
	degree_to_str(str, scan->pos.stop.lon, -1, DM_FORMAT_CODE);
	fprintf(fp, "%s  ", str);

	/* Determine good statistics */
	good_stat = 
		(scan->time.start < ADJ_BADFLOAT) 
		&& (scan->time.stop < ADJ_BADFLOAT)
		&& (scan->pos.start.lat < ADJ_BADFLOAT)
		&& (scan->pos.start.lon < ADJ_BADFLOAT)
		&& (scan->pos.stop.lat < ADJ_BADFLOAT)
		&& (scan->pos.stop.lon < ADJ_BADFLOAT);

	/* Heading, pitch and roll */
	if((scan->prh.heading.mean < ADJ_BADFLOAT) && good_stat)
		fprintf(fp, "%6.2f %5.2f %2d  ", 
						to360(scan->prh.heading.mean), 
						scan->prh.heading.sdev, 
						scan->prh.heading.npts);
	else
		fprintf(fp, "1.0E38 1.0E38  0  ");
	if((scan->prh.pitch.mean < ADJ_BADFLOAT) && good_stat)
		fprintf(fp, "%+6.2f %6.2f %2d  ", 
						scan->prh.pitch.mean, 
						scan->prh.pitch.sdev, 
						scan->prh.pitch.npts);
	else
		fprintf(fp, "1.0E38 1.0E38  0  ");
	if((scan->prh.roll.mean < ADJ_BADFLOAT) && good_stat)
		fprintf(fp, "%+6.2f %6.2f %2d  ", 
						scan->prh.roll.mean, 
						scan->prh.roll.sdev, 
						scan->prh.roll.npts);
	else
		fprintf(fp, "1.0E38 1.0E38  0  ");

	/* Course and speed data */
	if((scan->spd.course.mean < ADJ_BADFLOAT) && good_stat)
		fprintf(fp, "%+6.2f %6.2f %2d  ", 
						scan->spd.course.mean, 
						scan->spd.course.sdev, 
						scan->spd.course.npts);
	else
		fprintf(fp, "1.0E38 1.0E38  0  ");
	if((scan->spd.speed.mean < ADJ_BADFLOAT) && good_stat)
		fprintf(fp, "%+6.2f %6.2f %2d  ", 
						scan->spd.speed.mean, 
						scan->spd.speed.sdev, 
						scan->spd.speed.npts);
	else
		fprintf(fp, "1.0E38 1.0E38  0  ");

	/* End of line */
	fprintf(fp, "\n");

	return(0);

}

/* ------------------------------------------------------------------
	 This function reads the next [[scan_nav]] output line from a file. 
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int read_scan_nav_line(/* Input file */
                       FILE *fp, 
                       /* Pointer to place data */
                       SCAN_NAV_LINE_TYPE *scan, 
                       /* Year base */
                       int year_base)
#else
int read_scan_nav_line(fp, scan, year_base)
FILE *fp;
ENSEMBLE_TYPE *scan;
int year_base;
#endif
{

	int done, n;
	long ofs;
	YMDHMS_TIME_TYPE time;
	DMSH_POSITION_TYPE pos;
	char line[NAV_LINE_MAX_LENGTH];

	/* Loop until a good scan_nav line has been read */
	done = 0;
	while(!done){
	
		/* Skip over comment lines */
		line[0] = '%';
		while(line[0] == '%'){
			
			/* Keep position */
			ofs = ftell(fp);

			/* Get a whole line */
			if(fgets(line, NAV_LINE_MAX_LENGTH, fp) == NULL){
				if(feof(fp)) return(EOF);
				error_found(READ_ERROR, "Skipping over comment lines\n");
				return(READ_ERROR);
			}
		}
		
		/* Position file back */
		if(error_found(fseek(fp, ofs, SEEK_SET), 
									 "Positionning to beginning of line\n"))
			return(SEEK_ERROR);
	
		/* Read ensemble number */
    /* 1999/09/21 Pierre Jaccard
       We must test for the end of file, since this is the first element of
       the line */
    n = fscanf(fp, " %hu", &(scan->number));
    if(n != 1){
      if(feof(fp)) return(EOF);
      error_found(READ_ERROR, "Reading ensemble number\n");
			return(READ_ERROR);
    }

		/* Read start time */
		if(error_found(fget_ymdhmh_time(fp, &time), "Reading start time\n"))
			return(READ_ERROR);
		if(invalid_time(&time))
			scan->time.start = BADDOUBLE;
		else
			scan->time.start = year_day(&time, year_base);
		
		/* Read stop time */
		if(error_found(fget_ymdhmh_time(fp, &time), "Reading stop time\n"))
			return(READ_ERROR);
		if(invalid_time(&time))
			scan->time.stop = BADDOUBLE;
		else
			scan->time.stop = year_day(&time, year_base);

		/* Get start latitude */
		if(error_found(get_dmsh_position(fp, &pos, 1) < 0, 
                   "Reading start latitude\n"))
			return(READ_ERROR);
		if(invalid_position(&pos, 1))
			scan->pos.start.lat = BADDOUBLE;
		else
			scan->pos.start.lat = ((double) POSHUN(&pos))/360000.0;
		
		/* Get start longitude */
		if(error_found(get_dmsh_position(fp, &pos, -1) < 0, 
									 "Reading start longitude\n"))
			return(READ_ERROR);
		if(invalid_position(&pos, 0))
			scan->pos.start.lon = BADDOUBLE;
		else
			scan->pos.start.lon = ((double) POSHUN(&pos))/360000.0;
		
		/* Get stop latitude */
		if(error_found(get_dmsh_position(fp, &pos, 1) < 0, 
                   "Reading stop latitude\n"))
			return(READ_ERROR);
		if(invalid_position(&pos, 1))
			scan->pos.stop.lat = BADDOUBLE;
		else
			scan->pos.stop.lat = ((double) POSHUN(&pos))/360000.0;
		
		/* Get stop longitude */
		if(error_found(get_dmsh_position(fp, &pos, -1) < 0, 
                   "Reading stop longitude\n"))
			return(READ_ERROR);
		if(invalid_position(&pos, 0))
			scan->pos.stop.lon = BADDOUBLE;
		else
			scan->pos.stop.lon = ((double) POSHUN(&pos))/360000.0;
		
		/* Read heading, pitch and roll */
		if(error_found(fscanf(fp, "%lf %lf %d %lf %lf %d %lf %lf %d ", 
													&(scan->prh.heading.mean), &(scan->prh.heading.sdev),
													&(scan->prh.heading.npts),
													&(scan->prh.pitch.mean), &(scan->prh.pitch.sdev), 
													&(scan->prh.pitch.npts),
													&(scan->prh.roll.mean), &(scan->prh.roll.sdev), 
													&(scan->prh.roll.npts)) != 9,
									 "Reading heading, pitch and roll\n"))
			return(READ_ERROR);
		
		/* Read course and speed */
		if(error_found(fscanf(fp, "%lf %lf %d %lf %lf %d",
													&(scan->spd.course.mean), &(scan->spd.course.sdev), 
													&(scan->spd.course.npts),
													&(scan->spd.speed.mean), &(scan->spd.speed.sdev), 
													&(scan->spd.speed.npts)) != 6,
									 "Reading corse and speed\n"))
			return(READ_ERROR);
		
		/* 98/08/23 PJ
			 Require the ensemble number to be different from zero, since this 
			 ensemble seems usually to be a memory dump from the ADCP at start
			 up. */

		/* Loop exit flag */
		if((scan->time.start < ADJ_BADFLOAT) 
			 && (scan->time.stop < ADJ_BADFLOAT)
			 && (scan->pos.start.lat < ADJ_BADFLOAT)
			 && (scan->pos.start.lon < ADJ_BADFLOAT)
			 && (scan->pos.stop.lat < ADJ_BADFLOAT)
			 && (scan->pos.stop.lon < ADJ_BADFLOAT)
			 && (scan->number > 0))
			done = 1;
		else
			report_msg("\n%%% Bad scan_nav input line. Skipping...\n");
	}
   
   	/* 
	 * 2000/08/08 PJ
	 *            We must read up to the next line in order to prepare
	 *            for the next call to fgets() at next function call.
	 */
   	line[0] = '\0';	
   	while( (fscanf(fp, "%c", line) == 1) && (line[0] != '\n'));
     	if(line[0] != '\n'){
	   error_found(READ_ERROR, "Skipping rest of line\n");
	   return(READ_ERROR);
	}
			 
	return(0);

}

/* ------------------------------------------------------------------
	 If flag is negative, put bad values in all variables. Else, no action is
	 defined yet.
	 ------------------------------------------------------------------ */

#if PROTOTYPE_ALLOWED
int init_scan_nav_line(/* Pointer to navigation data */
                       SCAN_NAV_LINE_TYPE *scan, 
                       /* Must be negative at present */
                       int flag)
#else
int init_scan_nav_line(scan, flag)
#endif
{

	if(flag < 0){
		scan->number = BADUSHORT;
		scan->time.start = BADDOUBLE;
		scan->time.stop  = BADDOUBLE;
		scan->pos.start.lat = BADDOUBLE;
		scan->pos.stop.lat  = BADDOUBLE;
		scan->pos.start.lon = BADDOUBLE;
		scan->pos.stop.lon  = BADDOUBLE;
		scan->prh.heading.mean = BADDOUBLE;
		scan->prh.heading.sdev = BADDOUBLE;
		scan->prh.heading.npts = 0;
		scan->prh.pitch.mean = BADDOUBLE;
		scan->prh.pitch.sdev = BADDOUBLE;
		scan->prh.pitch.npts = 0;
		scan->prh.roll.mean = BADDOUBLE;
		scan->prh.roll.sdev = BADDOUBLE;
		scan->prh.roll.npts = 0;
		scan->spd.course.mean = BADDOUBLE;
		scan->spd.course.sdev = BADDOUBLE;
		scan->spd.course.npts = 0;
		scan->spd.speed.mean = BADDOUBLE;
		scan->spd.speed.sdev = BADDOUBLE;
		scan->spd.speed.npts = 0;
	}

	return(0);

}

