/*
 * $Id: main.c,v 2.12 89/11/11 19:13:48 tynor Exp $
 *----------------------------------------------------------------------------
 *	FPLAN - Flight Planner
 *	Steve Tynor
 *	tynor@prism.gatech.edu
 *
 *	This program is in the public domain. Permission to copy,
 * distribute, modify this program is hearby given as long as this header
 * remains. If you redistribute this program after modifying it, please
 * document your changes so that I do not take the blame (or credit) for
 * those changes.  If you fix bugs or add features, please send me a
 * patch so that I can keep the 'official' version up-to-date.
 *
 *	Bug reports are welcome and I'll make an attempt to fix those
 * that are reported.
 *
 *	USE AT YOUR OWN RISK! I assume no responsibility for any
 * errors in this program, its database or documentation. I will make an
 * effort to fix bugs, but if you crash and burn because, for example,
 * fuel estimates in this program were inaccurate, it's your own fault
 * for trusting somebody else's code! Remember, as PIC, it's _your_
 * responsibility to do complete preflight planning. Use this program as
 * a flight planning aid, but verify its results before using them.
 *----------------------------------------------------------------------------
 */

static char rcsid[] = "$Id: main.c,v 2.12 89/11/11 19:13:48 tynor Exp $";

#include <stdio.h>
#include "wp_info.h"
#include "version.h"

#define EXIT_GOOD 0
#define EXIT_BAD  1

extern FILE *yyin;
extern BOOLEAN open_dbs ();
extern BOOLEAN close_dbs ();
extern BOOLEAN compute_plan ();
extern void print_plan ();
extern void set_output_units ();
extern void set_format ();
extern void set_brief ();
extern char yytext[];
extern BOOLEAN lookup_desig ();
extern void put_db_summary ();
extern void print_reverse ();

/*
 * if any of the GFX_* options are defined, define GFX
 */
#ifdef GFX_SUNVIEW
#define GFX
#endif
#ifdef GFX_X
#undef GFX
#define GFX
#endif
#ifdef GFX_POSTSCRIPT
#undef GFX
#define GFX
#endif

/*----------------------------------------------------------------------------*/
static void do_lookup (desig)
     char *desig;
{
   DATABASE_INFO *db1 = (DATABASE_INFO*)0;
   DATABASE_INFO *db2 = (DATABASE_INFO*)0;

   if (lookup_desig (WP_VIA, desig, &db1))
      put_db (stdout, db1);

   if (lookup_desig (WP_FROM, desig, &db2))
      if (!db1 || (db1->mode != db2->mode))
	 put_db (stdout, db2);
}

/*----------------------------------------------------------------------------*/
static void init (brief)
     BOOLEAN brief;
{
   /* 
    * NOTE: we count on all variables being set to 0 (thus all optional values
    * are 'off' by default).
    */
   num_waypoints = 0;
   num_cached = 0;
   set_brief (brief);
}

/*----------------------------------------------------------------------------*/
static BOOLEAN parse_script ()
{
   return (BOOLEAN) (! yyparse ());
}

/*----------------------------------------------------------------------------*/
usage (progname)
     char *progname;
{
   fprintf (stderr, "FPLAN %s\n", VERSION);
   /*
    * LOOKUP mode:
    */
   fprintf (stderr, "usage: %s -l designator ...\n", progname);
   fprintf (stderr, "\t-l - lookup the designator(s) in the databases\n");

   /*
    * REVERSE mode:
    */
   fprintf (stderr, "    or\n");
   fprintf (stderr, "       %s -r [-|planfile]\n", progname);
   fprintf (stderr, "\t-r - compute the return trip, prints the reversed plan to stdout.\n");
   fprintf (stderr, "\t-  - read 'planfile' from the standard input.\n");

#ifdef GFX
   /*
    * GRAPHICS mode:
    */
   fprintf (stderr, "    or\n");
   fprintf (stderr, "       %s -g [-|planfile]\n", progname);

#ifdef GFX_SUNVIEW
   fprintf (stderr, "\t-g - preview the route graphically in a Sunview window\n");
#endif /* GFX_SUNVIEW */
#ifdef GFX_X
   fprintf (stderr, "\t-g - preview the route graphically in an X window\n");
#endif /* GFX_X*/
#ifdef GFX_POSTSCRIPT
   fprintf (stderr, "\t-g - create a PostScript program to draw the route\n");
#endif /* GFX_POSTSCRIPT*/
   fprintf (stderr, "\t-  - read 'planfile' from the standard input.\n");
#endif /* GFX */

   /*
    * NORMAL mode:
    */
   fprintf (stderr, "    or\n");
   fprintf (stderr, "       %s [-n|w][-b][-t][-s][-e][-|planfile]\n", 
	    progname);
   fprintf (stderr, "\t-n - selects the narrow (no VOR fixes) format form [default]\n");
   fprintf (stderr, "\t-w - selects the wide (VOR fixes) format form \n");
   fprintf (stderr, "\t-s - selects Statute miles for output format [default = Nautical]\n");
   fprintf (stderr, "\t-t - disable automatically tracking navaids in NAV1 [default = enabled]\n");
   fprintf (stderr, "\t-b - set BRIEF mode - ignore 'incremental' waypoints\n");
   fprintf (stderr, "\t-e - use Epson (PC) box characters on output form\n");
   fprintf (stderr, "\t-d - append a summary of all database objects used\n");
   fprintf (stderr, "\t-  - read 'planfile' from the standard input.\n");
   fprintf (stderr, "    the planfile format is described in FPLAN(1)\n");
   exit (EXIT_BAD);
}

/*----------------------------------------------------------------------------*/
int main (argc, argv)
     int argc;
     char *argv[];
{
   enum {WIDE, NARROW} format = NARROW;
   int i;
   BOOLEAN auto_nav1        = TRUE;
   BOOLEAN brief            = FALSE;
   BOOLEAN epson_box_chars  = FALSE;
   BOOLEAN reverse          = FALSE;
   BOOLEAN database_summary = FALSE;
#ifdef GFX_SUNVIEW
   BOOLEAN draw_sunview     = FALSE;
#endif
#ifdef GFX_X
   BOOLEAN draw_x           = FALSE;
#endif
#ifdef GFX_POSTSCRIPT
   BOOLEAN draw_postscript  = FALSE;
#endif

   if (argc < 2)
      usage (argv[0]);

   if (! open_dbs ())
      exit (EXIT_BAD);

   if ((argv[1][0] == '-') && (argv[1][1] == 'l')) {
      for (i = 2; i < argc; i++)
	 do_lookup (argv[i]);
      exit (EXIT_GOOD);
   }

   yyin = NULL;
   set_output_units (1);
   for (i = 1; i < argc; i++) {
      if (argv[i][0] == '-') {
	 switch (argv[i][1]) {
	 case 'g':
	    /* 
	     *leave these separate for now, we'll probably want to link in all
	     * three on some systems...
	     */
#ifdef GFX_SUNVIEW
	    draw_sunview = TRUE;
#endif
#ifdef GFX_X
	    draw_x = TRUE;
#endif
#ifdef GFX_POSTSCRIPT
	    draw_postscript = TRUE;
#endif
	    break;
	 case 'r':
	    reverse = TRUE;
	    break;
	 case 'e':
	    epson_box_chars = TRUE;
	    break;
	 case 'd':
	    database_summary = TRUE;
	    break;
	 case 's':
	    set_output_units (0);
	    break;
	 case 'n':
	    format = NARROW;
	    break;
	 case 'w':
	    format = WIDE;
	    break;
	 case 'b':
	    brief = TRUE;
	    break;
	 case 't':
	    auto_nav1 = FALSE;
	    break;
	 case '\0':
	    if (yyin) {
	       fprintf (stderr, 
			"ERROR: cannot read from stdin and planfile: \"%s\".\n",
			argv[i]);
	       usage (argv[0]);
	    } else {
	       yyin = stdin;
	    }
	    break;
	 default:
	    fprintf (stderr, "ERROR: unknown option: \"%s\".\n", argv[i]);
	    usage (argv[0]);
	    break;
	 }
      } else {
	 if (yyin) {
	    fprintf (stderr, "ERROR: only one planfile allowed: \"%s\".\n",
		     argv[i]);
	    usage (argv[0]);
	 } else {
	    yyin = fopen (argv[i], "r");
            if (! yyin) {
	       fprintf (stderr, "ERROR: could not open script file: %s.\n", 
			argv[i]);
	       usage (argv[0]);
	    }
	 }
      }
   }

   if (! yyin) {
      fprintf (stderr, "ERROR: no planfile\n");
      usage (argv[0]);
   }
   init (brief);

   if (! parse_script ())
      exit (EXIT_BAD);

   if (! compute_plan (auto_nav1) )
      exit (EXIT_BAD);

   if (reverse) {
      print_reverse ();
#ifdef GFX_SUNVIEW
   } else if (draw_sunview) {
      sv_draw (brief);
#endif
#ifdef GFX_X
   } else if (draw_x) {
      x_draw (brief);
#endif
#ifdef GFX_POSTSCRIPT
   } else if (draw_postscript) {
      ps_draw (brief);
#endif
   } else {
      if (format == NARROW)
	 max_nav = -1;
      else if (auto_nav1)
	 max_nav = MAX (0, max_nav);
      set_format (max_nav, epson_box_chars);
      
      print_plan ();

      if (database_summary)
	 put_db_summary (stdout);
   }

   if (! close_dbs ())
      exit (EXIT_BAD);
}


/*----------------------------------------------------------------------------*/
int yyerror(s)
char* s;
{
   extern int yylineno;

   fprintf (stderr, "ERROR: line %d: %s\n", yylineno, s);
   exit (EXIT_BAD);
}

/*----------------------------------------------------------------------------*/
int yywrap ()
{
   return (1);
}

/*----------------------------------------------------------------------------*/
int yyreject ()
{
   printf ("ERROR: parser rejecting %s\n", yytext);
   return (1);
}

