
	/* read information from a request file into memory so that other
	   routines can figure out whether, and when, to observe this object.
	   use the request files in the REQUEST_DIR directory. 

	   command line arguments: 

	                listgen  [ MM/DD/YYYY ]  [ sim ]

	   where
	          MM/DD/YYYY  tells date to use in generating list
	                        if no argument, use the system date.

	          sim         says to run a simulation, printing selected 
	                        objects to stdout and using an artificial clock
	                        (i.e. not waiting for actual exposure length).
	                        Useful for finding out what WOULD be observed in
	                        practice, without having to wait all night.
	 */
	                

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include "bait.h"
#include "pf.h"
#include "list.h"

#define BUFLEN    100
#define TELCO     "telco"	/* the program which actually observes a target */

static void slurp_input(/* int *num_grp */ );
static void next_group( /* struct s_group *group, int *num_grp */ );
static void reject_file( /* char *filename */ );

char *progname = "listgen";
char *usage = "usage: listgen  [MM/DD/YYYY] [sim]";

struct s_group *grp_list[MAX_TARGETS];

main(argc, argv)
int argc;
char *argv[];
{
	int i, num_grp, day, month, year, sim_flag;

	num_grp = 0;
	sim_flag = 0;

	for (i = 1; i < argc; i++) {
		if (strcmp(argv[i], "sim") == 0) {
			sim_flag = 1;
			set_ut(0.0);
			continue;
		}
		if (sscanf(argv[i], "%d/%d/%d", &month, &day, &year) != 3) {
			fprintf(stderr, "%s\n", usage);
			exit(-1);
		}
		else
			set_today(day, month, year);
	}

	slurp_input(&num_grp);

	sort_groups(grp_list, num_grp);

	do_stuff(grp_list, num_grp, sim_flag);

	exit(0);	
}

	/* read a list of request files from the NEWREQS file, and for each
	   file, read its information into the list of groups in memory. */

static void
slurp_input(num_grp)
int *num_grp;
{
	char buf[BUFLEN], rqsfile[BUFLEN], *ch;
	FILE *fp;
	struct s_group *group, *read_request();

	/* take input from the files in the TARGET_DIR directory */
	sprintf(buf, "%s%s", TARGET_DIR, NEWREQ_FILE);
	if ((fp = fopen(buf, "r")) == NULL) {
#ifdef VERBOSE
		fprintf(stderr, "%s.slurp_input: can't open file ..%s..\n", progname, buf);
#endif
		exit(-1);
	}
	while (fgets(buf, BUFLEN, fp) != NULL) {
		if ((ch = strchr(buf, '\n')) != NULL)
			*ch = '\0';
		sprintf(rqsfile, "%s%s", TARGET_DIR, buf);
		group = read_request(rqsfile);
		if (group == NULL) 
			reject_file(rqsfile);
		else
			next_group(group, num_grp);
	}
	fclose(fp);

	/* and now delete the new-request file, so that new requests will
	   be alone in the file when (and if) any come in */
	sprintf(buf, "%s%s", TARGET_DIR, NEWREQ_FILE);
	if (unlink(buf) != 0) {
#ifdef VERBOSE
		fprintf(stderr, "%s.main: can't unlink file %s\n", progname, buf);
#endif
	}
}
	

	/* make calls to 'select()' to get the next object, and actually call
	   'telco()' if 'sim_flag' is zero. Otherwise, just print out information
	   on the object. */ 

do_stuff(grp_list, num_grp, sim_flag)
struct s_group *grp_list[];
int num_grp, sim_flag;
{
	int day, month, year, status, pid;
	double ut, jd, jds, jde, jdstart, dt;
	char buf[BUFLEN], buf2[BUFLEN], newreqs[BUFLEN];
	struct s_group *grp, *select_group();
	struct stat s_stat;

	get_today(&day, &month, &year);
	get_ut(&ut);
	set_clock(day, month, year, ut);

	get_jd(day, month, year, ut, &jd);
	night_limits(jd, -TWI_DEGREES, &jds, &jde);
	if (sim_flag == 1) {
		read_clock(&jd, sim_flag);
		printf("#  Julian Date        RA        Dec      exp time  pri  name\n");
	}
	sprintf(newreqs, "%s%s", TARGET_DIR, NEWREQ_FILE);

	do {
		if (stat(newreqs, &s_stat) == 0) {
#ifdef DEBUG
			printf("  about to slurp NEWREQS: old num_grp %d ", num_grp);
#endif
			slurp_input(&num_grp);
#ifdef DEBUG
			printf(" new num_grp %d\n", num_grp);
#endif
			sort_groups(grp_list, num_grp);
		}
#ifdef DEBUG
		printf(" clock is %.4lf - looking for next group \n", jd);
#endif
		if ((grp = select_group(grp_list, num_grp, 0, jde)) == NULL) {
			if (sim_flag == 1) {
				advance_clock(3600.0);
#ifdef DEBUG
				printf(" select_group returns NULL - advance clock one hour\n");
#endif
			}
			else {
#ifdef DEBUG
				printf(" select_group returns NULL - sleep for one hour\n");
#endif
				sleep(3600);
			}
			read_clock(&jd, sim_flag);
			if (jd > jde)
				break;
		}
		else {
			read_clock(&jd, sim_flag);
			/* now, if the group has a set UT start, wait until that time */
			if (grp->utstart >= 0.0) {
				calc_jd(jd, grp->utstart, &jdstart);
				if (sim_flag == 1) {
#ifdef DEBUG
					printf(" fixed-UT: advancing clock by %d seconds ",
								(jdstart - jd)*86400.0);
#endif
					advance_clock((jdstart - jd)*86400.0);
				}
				else {
#ifdef DEBUG
					printf(" fixed-UT: sleeping for %d seconds ",
								(jdstart - jd)*86400.0);
#endif
					sleep((jdstart - jd)*86400.0);
				}
				read_clock(&jd, sim_flag);
#ifdef DEBUG
				printf(" time is now %.4lf\n", jd);
#endif
			}
			else {
				/* or else, if the group isn't ready yet, wait until it is */
			
				till_visible(grp, jd, &dt);
				if (dt > 0.0) {
					if (sim_flag == 1) {
#ifdef DEBUG
						printf(" till_visible: advancing clock by %.4lf sec ",
										dt*86400.0);
#endif
						advance_clock(dt*86400.0);
					}
					else {
#ifdef DEBUG
						printf(" till_visible: sleeping for %.4lf sec ",										dt*86400.0);
#endif
						sleep(dt*86400.0);
					}
					read_clock(&jd, sim_flag);
#ifdef DEBUG
					printf(" time now %.4lf\n", jd);
#endif
				}	
			}

			/* now, actually observe the group - or pretend to */
			if (sim_flag == 1) {
				printf("%14.4lf  ", MJD(jd));
				print_group(grp);
				advance_clock(grp->exp_time);
			}
			else {
				printf("JD = %.4lf  ", jd);
				if ((pid = fork()) != 0) {
					wait(&status);		/* high 8 bits contain return status */
				}
				else {
					sprintf(buf, "%s%s", BIN_DIR, TELCO);
					sprintf(buf2, "%s%s.rqs", TARGET_DIR, grp->reqid);
					execl(buf, TELCO, buf2, (char *) 0);
				}
			}
			grp->done_yet = 1;
			read_clock(&jd, sim_flag);
#ifdef DEBUG
			printf(" group successfully observed - time now %.4lf\n", jd);
#endif
		}
	} while (jd < jde);
#ifdef DEBUG
	printf(" ********  end of night  *********** \n");
#endif
}


	/* check to see if the group is visible tonight - if so, add it to the
	   list of candidate groups */

static void
next_group(group, num_grp)
int *num_grp;
struct s_group *group;
{
	if (group == (struct s_group *) NULL) {
		/* do nothing */
	}
	else if (group->vis_flag == 0) {
#ifdef DEBUG
		printf("%s.next_group: group w/ first member ..%s.. invis tonight\n",
					progname, group->object->name);
#endif
	}
	else {
		grp_list[(*num_grp)++] = group;
	}
}

	/* the given request file has some sort of problem - therefore, this
	   routine adds a line to the header which looks like this:

	           REJECTED= 'some reason for rejection'

	   or maybe something simpler, like

	           REJECTED= 'listgen finds group is invalid'

	   in any case, the request file is now marked for Death to take it... */

static void
reject_file(filename)
char *filename;
{
	char buf[PF_LEN + 1];
	pf_handle pf;

	if ((pf = pf_open(filename, 1, PF_EXIST)) < 0) {
#ifdef VERBOSE
		fprintf(stderr, "%s.reject_file: can't pf_open file %s to reject it\n",
				progname, filename);
#endif
		return;
	}
	pf_strtoval("listgen finds request invalid", buf);
	if (pf_putval(pf, "REJECTED", buf) < 0) {
#ifdef VERBOSE
		fprintf(stderr, "%s.reject_file: can't pf_putval REJECTED keyword into file %s\n",
				progname, filename);
#endif
		return;
	}
	pf_close(pf);	
}

