/**---------------------------------------------------------------------------
 ** 
 ** gps.c -- 
 ** 
 ** Author          : Pierre Jaccard
 ** Created On      : 1999/08/03 22:00:26
 ** Last Modified By: Pierre Jaccard
 ** Last Modified On: 1999/08/03 22:13:13
 ** Update Count    : 7
 ** Directory       : /home/pego/pcd1/codas3c/gfi/src/apps/nav/
 ** Version         : 0.0
 ** Status          : Unknown
 ** ---------------------------------------------------------------------- ** 
 ** DESCRIPTION: 
 ** 
 **    Undocumented.
 ** 
 ** ---------------------------------------------------------------------- ** 
 ** REVISIONS: 
 ** ---------------------------------------------------------------------- ** 
 ** CHANGES: 
 **------------------------------------------------------------------------**/

/* ##################################################################
	-Introduction:

	Utility to extract position fixes from GPS processed ascii files collected
	with two Azhtech receivers, as during AGMASCO-HM9720. Since refabs and
	refabsbt programmes read only 

	   time, 
		 longitude and 
		 latitude

	we do not need to output the rest (nsat, quality, etc ...) which in addition
	is not available in all of these files. 

	Additionnal output columns for diagnostic are:
	
	   4. status ([-1] = BAD_FIX, [1] = GOOD_FIX)
		 5. time from previous fix to ensemble in seconds
		 6. time from current fix to ensemble in seconds
		 
	##################################################################
*/

#include "gps.h"

#if PROTOTYPE_ALLOWED
int next_gps_fix(FILE *fp, GPS_FIX_TYPE *fix, int year_base)
#else
int ()
#endif
{

	double day, lat, lon;
	int n, done=0;
	char *t0;
	
	while(!done){

		/* Get next file name */
		if(!(fix->fp)){
			if( getword_nc(fp, fix->file, sizeof(FILE_NAME_TYPE)) <= 0){
				if(feof(fp))
					return(EOF);
				else
					return(READ_ERROR);
			}
		
			/* Information message */
			printf("\tGPS FILE: %s\n", fix->file);
		
			/* Get the time origin from the file name */
			t0 = strchr(fix->file, '.') + 1;
			if(error_found(t0 == NULL, "Cannot find suffix start"))
				return(1);
			sscanf(t0, "%d", &(fix->day_0));
			if(error_found( ((fix->day_0 < 1) || (fix->day_0 > 365)),
											"Time origin out of range"))
				return(1);
			
			/* Initialize the file */
			fix->fp = check_fopen(fix->file, "r");
		}
	
		/* Read data from gps fix line */
		n = fscanf(fix->fp, "%lf %*f %*f %*f %lf %lf %*f", &day, &lat, &lon);
		if(n != 3){
			if(feof(fix->fp)){
				/* Read next file */
				fclose(fix->fp);
				fix->fp = NULL;
			}
			else{
				error_found( 1, "While reading data from gps fix line");
				return(READ_ERROR);
			}
		}
		else
			done = 1;

		}

	/* Backup previous end data */
	fix->gps.day.start  = fix->gps.day.end;
	fix->gps.lon.start  = fix->gps.lon.end;
	fix->gps.lat.start  = fix->gps.lat.end;
	
	/* Check longitude */
	if((control_bits & LON_180_BIT) && (lon >= 180.0))
		lon -= 360.0;
	if(!(control_bits & LON_180_BIT) && (lon < 0.0))
		lon += 360.0;

	/* Convert time to correct decimal day */
	fix->gps.day.end = day / 86400.0 + fix->day_0;
	fix->gps.lon.end = lon;
	fix->gps.lat.end = lat;

	return(0);

}

/* ------------------------------------------------------------------
	 -MAIN:
	 ------------------------------------------------------------------ */
	
#if PROTOTYPE_ALLOWED
void do_it(FILE *fp_cnt)
#else
void do_it(fp_cnt)
#endif
{

	FILE *fp_lst, *fp_out;
	GPS_FIX_TYPE fix;
	TIME_RANGE_TYPE time;
	YMDHMS_TIME_TYPE this_time;
	DMSH_LL_TYPE this_pos;

	double dt0, dt1;
	int dbid = 1, dbam = READ_ONLY, dbmm = DIR_ON_DISK;
	int error = 0;
  unsigned int nbytes;
	char str[200];

	/* Get the parameters and options */
	if(get_parameters(fp_cnt, parameters, NULL))  exit(-1);
	print_parameters(stdout, parameters, NULL, "\n");

	if(execute_options(fp_cnt, options, 1)<=0){
		printf("\nERROR: while reading options.\n\n");
		exit(-1);
	}


	/* Initialize database and output files */
	check_dbopen(dbid, dbname, dbam, dbmm);
	fp_lst = check_fopen(gps_lst_file, "r");
	fp_out = check_fopen(gps_out_file, "w");
	fix.fp = NULL;
	fix.status = NO_FIX;
	
	/* Loop through time ranges */
	while(!error && (get_time_range(fp_cnt, &(time.start), &(time.end)) == 1)){
		
		/* Message */
		ymdhms_to_str(str, &(time.start), 1);
		printf("\n%%%% TIME RANGE: %s to ", str);
		ymdhms_to_str(str, &(time.end), 1);
		printf("%s\n", str);
			
		/* Initialize fix and position data base */
		if(!(fix.fp)){
			error = dbsrch_cnf(TIME_SEARCH, (char *) &(time.start));
			if(error_found( error && (error != SEARCH_BEFORE_BEGINNING),
											"Initializing database to first ensemble"))
				goto on_error;
			error = 0;
			if(error_found( next_gps_fix(fp_lst, &fix, year_base),
											"Initializing fix"))
				goto on_error;
		}
		
		/* Loop through database ensembles */
		while(!error && check_time(&this_time, &time.start, &time.end)){

			/* Get ADCP position */
			nbytes = sizeof(DMSH_LL_TYPE);
			error = dbget_cnf(POSITION, (char *) &this_pos, &nbytes, 
												"Getting position");
			
			/* Initialize fix */
			fix.day = year_day(&this_time, year_base);
			fix.lon = ((double) POSHUN(&(this_pos.lon))) / 360000.0;
			if((control_bits & LON_180_BIT) && (fix.lon >= 180.0))
				fix.lon -= 360.0;
			if(!(control_bits & LON_180_BIT) && (fix.lon < 0.0))
				fix.lon += 360.0;
			fix.lat = ((double) POSHUN(&(this_pos.lat))) / 360000.0;
			fix.status = NEXT_FIX;

			/* Loop through the fixes */
			while(!(error || (fix.status == BAD_FIX) || (fix.status == GOOD_FIX))){
				
				/* Get next fix */
				error = next_gps_fix(fp_lst, &fix, year_base);
				if(error)
					goto on_error;

				/* Check current ADCP time against GPS fix */
				dt0 = (year_day(&this_time, year_base) - fix.gps.day.start) * 86400.0;
				dt1 = (fix.gps.day.end - year_day(&this_time, year_base))   * 86400.0;
				if(dt0 < 0)
					fix.status = BAD_FIX;
				else if((dt0 >= 0) && (dt1 >= 0)){
					if((dt0 < (double)tolerance) && (dt1 < (double)tolerance))
						fix.status = GOOD_FIX;
					else
						fix.status = BAD_FIX;
				}
				else
					fix.status = NEXT_FIX;
			}
			
			/* Calculate fix */
			if(fix.status == GOOD_FIX){
				fix.lon = fix.gps.lon.end - 
					dt1/(dt0 + dt1) * (fix.gps.lon.end - fix.gps.lon.start);
				fix.lat = fix.gps.lat.end -
					dt1/(dt0 + dt1) * (fix.gps.lat.end - fix.gps.lat.start);
			}

			/* Write the fix */
			if((control_bits & ONLY_GOOD_FIX_BIT) && (fix.status != GOOD_FIX))
				fix.status = NEXT_FIX;

			if((fix.status == GOOD_FIX) || (fix.status == BAD_FIX)){
				fprintf(fp_out, "%15.8f %15.8f %15.8f %3d %15.2f %15.2f\n", 
								fix.day, fix.lon, fix.lat, fix.status, dt0, dt1);
			}
			
			/* Next ensemble */
			error = dbmove_cnf(1);

		} /* Loop through ADCP ensembles */ 

	} /* Loop through time ranges */

	/* Check error for end of database */
	if(error && (error == SEARCH_BEYOND_END))
		error = 0;
	
on_error:
	
	fclose(fp_out);
	fclose(fp_lst);
	if(fix.fp)
		fclose(fix.fp);
	
	if(error){
		if(error == EOF)
			printf("\n\nGPS ended at EOF\n\n");
		else
			printf("\n\n!!! GPS ended with error !!!\n\n");
	}
	else{
		printf("\n\nGPS ended normally\n\n");
	}

	return;
	
}





