/* irserver.c

	Copyright (c) Kapteyn Laboratorium Groningen 1991
	All Rights Reserved.

#>	      irserver.dc2

Document:     IRSERVER

Purpose:      Describes the IRAS data server interface.

Category:     IRAS, SYSTEM

File:	      irserver.c

Author:       A.R.W. de Jonge

Description:  The irserver routines are an interface between files on a IRAS
	      data server and the GIPSY environment.

	      The IRAS data are stored on the server as files with a FITS
	      structure. The IRSERVER_OPEN or IRSERVER_SCAN routines
	      can be used to collect one or more of these data files into a
	      scratch directory, making it (read-only) accessable for the
	      FITS routines (see FTS_IO.DC2).
	      The routine IRSERVER_CLOSE subsequently destroys this
	      directory, reclaiming the space.

	      An example of use would be:

		mtid = IRSERVER_OPEN ( ... )		| select data
		REPEAT
			FTSD_GETH ( mtid, ... ) 	| read header
			...
			FTSI_GETR ( mtid, ... ) 	| read data
			...
			skip = FTS_SKIPFIL ( mtid, 1 )	| next file
		UNTIL ( skip .eq. -13 ) 		| (if present)
		IRSERVER_CLOSE ( mtid ) 		| clean up scratch space

	      Additional utility routines present in the interface are:

	      IRSERVER_SEARCH	Searches the IRAS index file

	      Each routine is described in more detail in the
	      appropriate document.

	Related Docs: mtiodev.dc2, fts_io.dc2

Updates:      Jul 13, 1993: AdJ Added irserver_scan
	      Nov 28, 1991: AdJ Check on existence of retrieved files
	      Aug 23, 1991: AdJ Document created.

#<
*/

/* Imports from the outside world */

#include "stdio.h"
#include "math.h"
#include "string.h"
#include "stdlib.h"

#include "gipsyc.h"
#include "nelc.h"
#include "mtopen.h"
#include "mtclose.h"
#include "ircc_obsmode.h"
#include "ircc_bandnr.h"
#include "iras_root.h"

#include "userfio.h"
#include "taskcom.h"
/*
	#include "atfinis.h"	does not work again
 */
	int atfinis ( CleanProc, void *);

#include "irserver_open.h"
#include "irserver_close.h"
#include "irserver_search.h"
#include "irserver_scan.h"

/* General definitions */

#define IRS_LINESIZE	65
#define IRS_INDTYP_LEN	10
#define IRS_LINESTR	( IRS_LINESIZE + 1 )
#define IRS_ERROR_TYPE	-1
#define IRS_ERROR_FILE	-2
#define IRS_ERROR_ALL	-2
#define IRS_KEY_OFFSET	45

static char * index_of_set ( fchar );
static char * alloc_space ( void );
static void destroy_space ( char **  );
static void destroy_all ( void * );
static char * indexfilename ( char * );
static int movetotarget ( char *, char *, int );
static char * map_index_to_filename ( fchar , fchar );
static char * map_sopatt_to_filename ( fint , fint , fchar );

#include "stdarg.h"


/*
#>	      irserver_open.dc2

Function:     IRSERVER_OPEN

Purpose:      Accesses IRAS server data of the specified type for the specified
	      area of sky.

Category:     IRAS, SYSTEM

File:	      irserver.c

Author:       A.R.W. de Jonge

Use:	INTEGER IRSERVER_OPEN (
		ECL_LON,		Input	real
		ECL_LAT,		Input	real
		RADIUS, 		Input	real
		INSTRUMENT )		Input	character*(*)

	IRSERVER_OPEN
		A non-negative number indicates that the
		call was successfull. This number is equivalent
		to the MTID returned by a succesfull call to
		MTOPEN, see MTOPEN.DC2. It must be used in
		successive calls to the fits or mtio routines.
		A negative number denotes one of
		the following errors:
			-1	Illegal INSTRUMENT
			-2	Cannot allocate and use disk space
	ECL_LON
		Ecliptic longitude of the center of the search area,
		epoch 1983.5, radians.
	ECL_LAT
		Ecliptic latitude of the center of the search area,
		epoch 1983.5, radians.
	RADIUS
		Search radius in radians. Any scan which passes witin
		RADIUS from the specified center, will be included
		in the resulting dataset.
	INSTRUMENT
		One of the possible instrument names for IRAS data,
		as described in IRCC_INSTRNAME.DC2,
		eg. 'AO b1', 'survey b2', etc.


	A call to IRSERVER_OPEN replaces an MTOPEN when accessing IRAS
	data on an IRAS data server.
	The resulting MTID identifies a disk-space containing
	(references to or copies of) the requested IRAS data,
	in a read-only form compatible with the MTIODEV interface.

	The user should call IRSERVER_CLOSE to destroy the scratch disk space
	claimed by these utilities.

	Related Docs:	irserver.dc2, irserver_close.dc2
			mtiodev.dc2, mtopen.dc2, fts_io.dc2
			ircc_const.dc2, ircc_instrname.dc2

Updates:      Feb 25, 1992: AdJ Bug (skips first file) repaired.
	      Aug 23, 1991: AdJ Document created.

#<

Fortran to C interface:

@ integer function irserver_open( real, real, real, character )

*/

/* hidden interface between irserver_open and irserver_close */
typedef struct {	fint	mtid ;
			char	* name ;
			} irastape ;
static irastape * tapelist ;
static int	tapecount = 0 ;

static irastape * newtape ( void )
{	/* search unused entry in tapelist, if not, extend tapelist.
	   if allocation of new tapelist or diskspace fails,
		make slot unused and return NULL.
	   return slot with name filled but mtid undefined.
	 */

	irastape * this = & tapelist[0] ;
	while ( this < & tapelist[tapecount] && this->mtid >= 0 ) this++ ;
	if ( this == & tapelist[tapecount] ) {
		void * newlist = tapecount ?
			realloc ( tapelist, (tapecount+1) * sizeof (irastape) ):
			malloc ( sizeof(irastape) );
		if ( newlist == NULL ) {
			errorf ( 3, " Out of memory in irserver_open" );
			return NULL ;
			}
		if ( tapecount == 0 ) {
			/* should register destroy_all with abort as well */
			atfinis ( destroy_all, NULL );
			}
		tapelist = (irastape *) newlist ;
		this = & tapelist[tapecount++] ;
		}
	this->name = alloc_space ( );
	if ( this->name == NULL ) { this->mtid = -1 ; return NULL ; }
	return this ;
	}

fint irserver_open_c ( float * lon, float * lat, float * rad, fchar dataset )
{
	fchar		indexline, indextype ;
	irastape	* thistape ;
	char		line[IRS_LINESTR], * file ;
	fint		found ;
	int		count_index, count_target ;

	indexline.a = line ; indexline.l = IRS_LINESIZE ;
	indextype.a = index_of_set ( dataset );
	indextype.l = strlen ( indextype.a );
	thistape = newtape() ;
	if ( thistape == NULL ) {
		errorf( 3," No space for new IRSERVER tape" );
		return IRS_ERROR_ALL ;
		}
	anyoutf ( 16, "irserver_open using name %s", thistape->name );
	count_index = count_target = 0 ;
	while ( 1 == ( found = irserver_search_c
			( lon, lat, rad, indextype, indexline )
		) ) {
		file = map_index_to_filename ( indexline, dataset );
		if ( file ) {
			anyoutf ( 16, "selected file %s", file );
			if ( movetotarget ( file, thistape->name,
							count_target+1 ) )
				count_target ++ ;
			}
		else errorf ( 3, "cannot get filename for %.*s",
			nelc_c(indexline), indexline.a );
		count_index ++ ;
		}
	if ( found < 0 ) {
		errorf ( 3, " IRSERVER_SEARCH error code %d", found );
		destroy_space ( & thistape->name );
		return IRS_ERROR_ALL ;
		}
	anyoutf ( 16, "irserver_open: %d scans in index, %d on disk",
		count_index, count_target );
	thistape->mtid = mtopen_c ( tofchar ( thistape->name ) );
	if ( thistape->mtid >= 0 ) return thistape->mtid ;
	errorf ( 3, " irserver_open detected mtopen error %d", thistape->mtid );
	destroy_space ( & thistape->name );
	return IRS_ERROR_ALL ;
	}

/*
#>	      irserver_scan.dc2

Function:     IRSERVER_SCAN

Purpose:      Accesses IRAS server data of the specified type for the specified
	      scan(s)

Category:     IRAS, SYSTEM

File:	      irserver.c

Author:       A.R.W. de Jonge

Use:	INTEGER IRSERVER_SCAN (
		SOP,			Input	integer(*)
		ATT,			Input	integer(*)
		COUNT,			Input	integer
		INSTRUMENT )		Input	character*(*)

	IRSERVER_SCAN
		A non-negative number indicates that the
		call was successfull. This number is equivalent
		to the MTID returned by a succesfull call to
		MTOPEN, see MTOPEN.DC2. It must be used in
		successive calls to the fits or mtio routines.
		A negative number denotes one of
		the following errors:
			-1	Illegal INSTRUMENT
			-2	Cannot allocate and use disk space
	SOP
		Array with SOP numbers of requested scans.
	ATT
		Array with ATT numbers of requested scans.
	COUNT
		Number of scans requested. For each scan I, the
		array elements SOP(I) and ATT(I) uniquely identify
		a scan. The data set for that scan, as identified further
		by INSTRUMENT, are put into the dataset.
	INSTRUMENT
		One of the possible instrument names for IRAS data,
		as described in IRCC_INSTRNAME.DC2,
		eg. 'AO b1', 'survey b2', etc.


	A call to IRSERVER_OPEN replaces an MTOPEN when accessing IRAS
	data on an IRAS data server.
	The resulting MTID identifies a disk-space containing
	(references to or copies of) the requested IRAS data,
	in a read-only form compatible with the MTIODEV interface.

	The user should call IRSERVER_CLOSE to destroy the scratch disk space
	claimed by these utilities.

	Related Docs:	irserver.dc2, irserver_close.dc2
			mtiodev.dc2, mtopen.dc2, fts_io.dc2
			ircc_const.dc2, ircc_instrname.dc2

Updates:      Jul 13, 1993: AdJ Added irserver_scan

#<

Fortran to C interface:

@ integer function irserver_scan( integer, integer, integer, character )

*/


fint irserver_scan_c ( fint * sop, fint * att, fint * count, fchar dataset )
{
	irastape	* thistape ;
	char		* file ;
	int		count_request, count_target ;

	thistape = newtape() ;

	if ( thistape == NULL ) {
		errorf( 3," No space for new IRSERVER tape" );
		return IRS_ERROR_ALL ;
		}
	anyoutf ( 16, "irserver_scan using name %s", thistape->name );
	count_target = 0 ;
	for ( count_request = 0 ; count_request < * count ; count_request++ ){
		file = map_sopatt_to_filename ( sop[count_request],
			att[count_request], dataset );
		if ( file ) {
			anyoutf ( 16, "selected file %s", file  );
			if ( movetotarget ( file, thistape->name,
							count_target+1 ) )
				count_target ++ ;
			}
		else errorf ( 3,
			"No file name for sop %d att %d dataset '%.*s'",
			sop[count_request], att[count_request],
			nelc_c(dataset), dataset.a );
		}
	anyoutf ( 16, "irserver_scan: %d scans asked, %d on disk",
		* count, count_target );
	thistape->mtid = mtopen_c ( tofchar ( thistape->name ) );
	if ( thistape->mtid >= 0 ) return thistape->mtid ;
	errorf ( 3, " irserver_scan detected mtopen error %d", thistape->mtid );
	destroy_space ( & thistape->name );
	return IRS_ERROR_ALL ;
	}

/*
#>	      irserver_close.dc2

Function:     IRSERVER_CLOSE

Purpose:      Reclaims disk space used by IRSERVER_OPEN or IRSERVER_SCAN

Category:     IRAS, SYSTEM

File:	      irserver.c

Author:       A.R.W. de Jonge

Use:	IRSERVER_CLOSE (
		MTID	)		Input	integer

	MTID	The reference to a subset of the IRAS data as
		returned by a succesfull call to IRSERVER_OPEN

	A call to IRSERVER_OPEN or IRSERVER_SCAN replaces an MTOPEN when
	accessing IRAS data on an IRAS data server.
	The resulting MTID identifies a disk-space containing
	(references to or copies of) the requested IRAS data,
	in a read-only form compatible with the MTIODEV interface.

	The user MUST call IRSERVER_CLOSE to destroy the scratch disk space
	claimed by these utilities.

	Related Docs:	irserver.dc2, irserver_open.dc2, irserver_scan.dc2

Updates:      Jul 14, 1993: AdJ Added irserver_scan
	      Aug 23, 1991: AdJ Document created.

#<

Fortran to C interface:

@ subroutine irserver_close( integer )

*/

void irserver_close_c ( fint * mtid )
{	irastape * tape = & tapelist [ 0 ] ;
	while ( tape < & tapelist[tapecount] ){
		if ( tape->mtid == * mtid ) {
			mtclose_c ( & tape->mtid );
			tape->mtid = -1 ;
			destroy_space ( & tape->name );
			}
		tape++ ;
		}
	return ;
	}

/*
#>	      irserver_search.dc2

Function:     IRSERVER_SEARCH

Purpose:      Searches the index file on a IRAS data server for scans
	      near a given position on the sky.

Category:     IRAS, SYSTEM

File:	      irserver.c

Author:       A.R.W. de Jonge

Use:	INTEGER IRSERVER_SEARCH (
		ECL_LON,		Input	real
		ECL_LAT,		Input	real
		RADIUS, 		Input	real
		INDEXTYPE,		Input	character
		INDEXLINES )		Output	character

	IRSERVER_SEARCH
		The number of lines found in the index,
		matching the search criterium, and fitting into the
		string INDEXLINES.
		If the return value is negative, it indicates an error:
			-1:	Illegal INDEXTYPE
			-2:	Index files could not be found.
	ECL_LON
		Ecliptic longitude of the center of the search area,
		epoch 1983.5, radians.
	ECL_LAT
		Ecliptic latitude of the center of the search area,
		epoch 1983.5, radians.
	RADIUS
		Search radius in radians. Any scan which passes witin
		RADIUS from the specified center to within one degree
		accuracy, is considered to be found in this search.
	INDEXTYPE
		One of 'AO', 'survey', or 'all'
	INDEXLINES
		A character string to receive the line(s) found from the
		index file. The amount of data found, as indicated
		by the function return value, will be truncated
		or blank-filled to match the length of the string
		INDEXLINES. Each line is 65 characters, formatted as
			??????

	Consecutive calls to this function with the same search
	parameters will retrieve different subsets of the index, until
	a zero return value indicates that no more data remain.

	A call with different search parameters is necessary to
	re-initialize the search.


	Example of use:
		parameter ( linesize = 65 )

		repeat
			count = IRSERVER_SEARCH ( 0.0, 89.0, 1.0, 'AO', text )
			line = 0
			while ( line .lt. count )
				first = 1 + line * linesize
				line = line + 1
				last = min ( len(text), line * linesize )
				print *, text ( first:last )
			endwhile
		until count .le. 0
		if ( count .lt. 0 ) print *, 'error code', count





	Related Docs:	irserver.dc2

Updates:      Aug 26, 1991: AdJ Document created.

#<

Fortran to C interface:

@ integer function irserver_search( real, real, real, character, character )

*/

#define DEGR		(3.141592653589793238462643383279502884 /180)


/* global variables used in the irserver_search context */

static FILE	* index = NULL ;
static float	x_ecl_plate = 0.6 , y_ecl_plate = 0.8, z_ecl_plate = 0.0 ;
static float	margin_plate = 10 ;
static float	sintab[541], * costab = & sintab[90] ;

static char * getline ( void );
static int indexguess ( char * );
static int psi_check ( char * );

fint irserver_search_c ( float * par_lng, float * par_lat, float * par_rad,
		fchar par_indextype, fchar indexlines )
{
	static float	lng = 0, lat = 0 , radius = -1 ;
	static char	indextype[IRS_INDTYP_LEN] = " " ;


	fint		count ;
	char		* nextline ;

	if ( ! (	lng == *par_lng
		&&	lat == *par_lat
		&&	radius == *par_rad
	&&	strncmp ( par_indextype.a, indextype,
				strlen(indextype) ) == 0
		)) {
			lng = * par_lng ;
			lat = * par_lat ;
			radius = * par_rad ;
			indextype[0] = '\0' ;
			count = nelc_c ( par_indextype );
			if ( count >= IRS_INDTYP_LEN ) return IRS_ERROR_TYPE ;
			char2str ( par_indextype, indextype, count+1 );
			anyoutf ( 16,
				"irserver_search '%s': lng %g lat %g rad %g",
				indextype, lng /DEGR, lat /DEGR, radius/DEGR );
			x_ecl_plate = cos(lng) * cos(lat) ;
			y_ecl_plate = sin(lng) * cos(lat) ;
			z_ecl_plate = sin(lat) ;
			margin_plate = (int)(radius/DEGR + 0.5 );
			if ( margin_plate < 1 ) margin_plate = 1 ;
			if ( strcmp ( indextype, "AO" ) != 0 &&
			     strcmp ( indextype, "survey" ) != 0 &&
			     strcmp ( indextype, "unknown" ) != 0 &&
			     strcmp ( indextype, "all" ) != 0 ) {
				errorf ( 3,
				"irserver_search illegal indextype '%s'",
					indextype );
				return IRS_ERROR_TYPE ;
				}
			index = fopen ( indexfilename(indextype), "r" );
			if ( index == NULL ) {
				errorf ( 3,
				"irserver_search cannot open file '%s'",
				indexfilename(indextype) );
				indextype[0] = '\0' ;
				return IRS_ERROR_FILE ;
				}
			}
	count = 0 ;
	while ( count < indexlines.l / IRS_LINESIZE && index != NULL ) {
		nextline = getline ();
		if ( ! nextline ) {
			fclose ( index );
			index = NULL ;
			indextype[0] = '\0' ;
			}
		else if ( indexguess ( nextline ) ){
			strncpy ( & indexlines.a[count*IRS_LINESIZE],
				nextline, IRS_LINESIZE );
			count++ ;
			}
		}
	return count ;
	}

static char * getline ( void )
{	static char result [IRS_LINESTR] ;
	if ( index == NULL ) return NULL ;
	if ( fread ( result, IRS_LINESTR, 1, index ) != 1 ) return NULL ;
	return result ;
	}


static int indexguess ( char * indexline )
{	int long_sun, theta_scan, theta_low, theta_high ;
	float z_sun_plate ;
	static int first = 0 ;
	if ( first == 0 ) for ( first = 0 ; first <= 90 ; first ++ )
		sintab[180+first] = sintab[360-first] = - (
			sintab[first] = sintab[180-first] = sintab[360+first] =
			sin((float)first * DEGR )
			);
	long_sun =	10 * ( 10 * indexline[0] + indexline[1] ) + indexline[2]
			 - ( 100 * '0' + 10 * '0' + '0' ) ;
	theta_scan =	10 * indexline[3] + indexline[4]
			+	IRS_KEY_OFFSET - 10 * '0' - '0';
	z_sun_plate = x_ecl_plate * costab[long_sun]
			+ y_ecl_plate * sintab[long_sun] ;
	theta_low = theta_scan - margin_plate ;
	if ( theta_low < 0 ) theta_low = 0 ;
	theta_high = theta_scan + margin_plate ;
	if ( theta_high > 180 ) theta_high = 180 ;
	if ( costab[theta_low] >= z_sun_plate
				&& z_sun_plate >= costab[theta_high] )
		return psi_check ( indexline );
	else	return 0 ;
	}

static int psi_check ( char * line )
{	float psinul, psidot, dur, cosd ;
	float x_sun_plate, y_sun_plate ;
	float x_sun_midscan, y_sun_midscan ;
	int lsun, psi, allowsiz ;

/* method: get rectangular coordinates of midpoint of scan and plate.
	then cos(distance-in-psi) = ( x1 * x2 + y1 * y2 ) / norm
	allowed distance in psi is half the scan length plus plate margin.
*/
	sscanf ( line, "%3d%*2c%f%f%*f%*d%f",
		& lsun, & psinul, & psidot, & dur );
	if ( psidot * dur >= 360 || psidot * dur <= -360 ) return 1 ;
			/* full-circle scan ?? */

	x_sun_plate = z_ecl_plate ;
	y_sun_plate = - y_ecl_plate * costab[lsun] +
		x_ecl_plate * sintab[lsun] ;
	psi = (int)( psinul + 0.5 * psidot * dur + 720.5 ) % 360 ;
	allowsiz = (int)(
		0.5 * ( psidot > 0 ? psidot : -psidot ) * dur
		+ margin_plate + 0.5 );
	x_sun_midscan = costab[psi] ;
	y_sun_midscan = sintab[psi] ;
	cosd = ( x_sun_midscan * x_sun_plate + y_sun_midscan * y_sun_plate ) /
		sqrt ( y_sun_plate * y_sun_plate  + x_sun_plate * x_sun_plate );
	return cosd > costab[allowsiz] ;
	}


static char * map_index_to_filename ( fchar indexentry, fchar dataset )
{	int	sop, att ;

	if ( sscanf ( indexentry.a, "%*46c%d%d", & sop, & att ) != 2 ){
		errorf ( 3, " bad syntax on line from indexfile" );
		return NULL ;
		}
	return map_sopatt_to_filename ( (fint)sop, (fint)att, dataset ) ;
	}



/* Details of the specific server implementation should be restricted
	to the following routines */

#ifndef __unix__
#error	UNIX beyond here: filenames, symbolic links, directory access etc.
#endif

static char * indexfilename ( char * type )
{
	static char	namebuff[255] ;
	static fchar	fnamebuff = { namebuff, 254 } ;
	fint		rootlen ;

	rootlen = iras_root_c( fnamebuff ) ;
	sprintf ( &(namebuff[rootlen]), "/index/%s_scans.index", type );
	return namebuff ;
	}

static char *indexmap[] = { "all", "survey", "survey", "AO", "all", "unknown" };

static char * index_of_set ( fchar instrument )
{	return indexmap [ ircc_obsmode_c(instrument) ] ;
	}


static char * alloc_space ( void )
{	/* return, if possible, a pointer to an 'malloc'ated string,
	 the string naming a disk space suitable for 'movetotarget' )
	 */
	char * result ;
	static int count = 0 ;
	extern int getpid(), mkdir() ;
	result = (char*)malloc(100) ;
	if ( result == NULL ) { errorf ( 3, "Out of memory" ); return NULL ; }
	sprintf ( result, "/tmp/irserver.%d.%d", getpid(), ++count );
	if ( mkdir ( result, 0777 ) != 0 ) {
		errorf ( 3, "cannot create directory %s", result );
		free ( result );
		return NULL ;
		}
	return result ;
	}

/* #include <unistd.h> this fail because of a redefinition of types */
#define R_OK 4 /* proceed with fingers crossed */

static int movetotarget ( char * file, char * target, int count )
{	char targetname[255] ;
	extern int symlink (), access() ;
	if ( strlen ( target ) + 14 >=	255 ) return 0 ;
	sprintf ( targetname, "%s/file%06d.mt", target, count );
	return access ( file, R_OK ) == 0 && symlink ( file, targetname ) == 0 ;
	}


/* The next map should be replaced whenever the directory naming on
	the server is consistent with the string returned by IRCC_INSTRNAME */

static char *obsmodemap[] =
	{ "", "survey", "splines", "AO", "flashes", "unknown" } ;
static char *bandnrmap[] = { "", "b1", "b2", "b3", "b4", "lrs", "bphf" } ;


static char * map_sopatt_to_filename ( fint sop, fint att, fchar dataset )
{	static char	result[255] ;
	static fchar	fresult = { result, 254 } ;
	fint		obsmode = ircc_obsmode_c ( dataset );
	fint		bandnr	= ircc_bandnr_c ( dataset );
	fint		rootlen ;

	if ( obsmode == 0 || bandnr == 0 ){
		errorf ( 3, "illegal dataset '%.*s'",
				nelc_c(dataset), dataset.a );
		return NULL ;
		}
	rootlen = iras_root_c( fresult ) ;
	sprintf ( &(result[rootlen]), "/%s.%s/sop.%02d_/%03d%03d",
		obsmodemap[obsmode], bandnrmap[bandnr], sop/10, sop, att );
	return result ;
	}

static void destroy_space ( char ** space )
{	int system ();
	char command[255] ;
	(void) system( strcat ( strcpy( command, "rm -r " ), *space ) );
	free ( *space );
	*space = NULL ;
	return ;
	}

static void destroy_all ( void * ignored )
{	irastape * this =  & tapelist[0] ;
	while ( this < & tapelist[tapecount] ) {
		if ( this->name ) destroy_space ( & this->name );
		this ++ ;
		}
	}

#ifdef TESTBED
#include "cmain.h"
#include "init.h"
#include "finis.h"
#include "pause.h"
#include "userlog.h"
#include "userint.h"
#include "usertext.h"
#include "userreal.h"
#include "canall.h"
#include "sortia.h"

static fint Zero = 0, One = 1 , Two = 2 , Three = 3, Four = 4 ;

MAIN_PROGRAM_ENTRY
{	bool proceed = toflog ( TRUE ) ;
	float lng, lat, rad ;
	fchar instr ;
	char instr_str[255] ;
	fint result, sopatts[100], MaxSopAtts = 100, count;

	instr.a = instr_str ; instr.l = 255 ;

	init_c() ;
	while ( tobool(proceed) ){
		canall_c () ;
		(void) usertext_c ( instr, & Zero,
			tofchar("INSTRUMENT="),
			tofchar("IRAS instrument to select data from")
			);
		count = userint_c ( sopatts, & MaxSopAtts, & One,
			tofchar("SOPATT="),
			tofchar("SOP ATT combination(s) to select [none]" )
			);
		if ( count == 0 ) {
			(void) userreal_c ( & lng, & One, & Zero,
				tofchar("LONG="),
				tofchar("Ecl. longitude of center (degrees) ")
				);
			(void) userreal_c ( & lat, & One, & Zero,
				tofchar("LAT="),
				tofchar("Ecl. latitude of center (degrees) ")
				);
			(void) userreal_c ( & rad, & One, & Zero,
				tofchar("RADIUS="),
				tofchar("Search radius (degrees) ")
				);
			anyoutf ( 0, " testbed long %g lat %g radius %g",
				lng, lat, rad );
			lng *= DEGR ;
			lat *= DEGR ;
			rad *= DEGR ;
			result = irserver_open_c ( & lng, & lat, & rad, instr );
			anyoutf ( 0, "irserver_open returns %d", result );
			}
		else if ( count % 2 != 0 ) {
			anyoutf ( 0, "SOPATT= requires pairs of numbers" );
			continue ;
			}
		else {	int i ;
			for ( i = 0; i < count/2 ; i ++ )
				sopatts[2*i+1] += 100000 ;
			sortia_c ( sopatts, & count );
			count /= 2;
			for ( i = 0 ; i < count ; i ++ )
				sopatts[count+i] -= 100000 ;
			result = irserver_scan_c ( sopatts, sopatts+count,
				& count, instr );
			anyoutf ( 0, "irserver_scan returns %d", result );
			}
		pause_c( tofchar ( "Ready for processing/inspection" ));
		irserver_close_c ( & result );
		(void) userlog_c ( & proceed, & One, & One,
			tofchar("PROCEED="),
			tofchar(" Continue testing ? [Yes]")
			);
		}
	finis_c();
	return EXIT_SUCCESS ;
	}
#endif

