/******************************************************************************
    Xplanet 0.43 - render an image of the earth into an X window
    Copyright (C) 1999 Hari Nair <hari@alumni.caltech.edu>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

******************************************************************************/

#include <iostream.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include "checkfuncs.h"
#include "options.h"
#include "util.h"
#include "xplanet.h"

options opts;

void 
usage (const char *msg)
{
  if (msg != NULL) cerr << msg << endl;
  cerr << "Use \"xplanet --help\" for a list of valid options\n";
  exit (EXIT_FAILURE);
}

void 
process_args (int argc, char **argv)
{
  srandom ((unsigned int) opts.time.tv_sec);
  for(int i=1; i<argc; i++) 
    {
      if (strncmp (argv[i],"--help",3) == 0) 
	{
	  cout << "valid options:\n";
	  cout << "\t--a[nimate]\n";
	  cout << "\t--ba[ckground]         image_file (char *)\n";
	  cout << "\t--bl[end]\n";
	  cout << "\t--bo[dy]               body       (int)\n";
	  cout << "\t--ce[nter]             x,y        (int, int)\n";
	  cout << "\t--cl[oud_image]        image_file (char *)\n";
	  cout << "\t--co[lor]              colorname  (char *)\n";
	  cout << "\t--dat[e]               string     (char *)\n";
	  cout << "\t--day[side]\n";
	  cout << "\t--demf[ile]            dem_file   (char *)\n";
	  cout << "\t--dems[cale]           scale      (float)\n";
	  cout << "\t--e[arthside]\n";
	  cout << "\t--fo[nt]               fontname   (char *)\n";
	  cout << "\t--fu[zz]               pixels     (int)\n";
	  cout << "\t--geometry             string     (char *)\n";
	  cout << "\t--grid                 spacing    (int)\n";
	  cout << "\t--grids[pace]          spacing    (int)\n";
	  cout << "\t--h[elp]\n";
	  cout << "\t--i[mage]              image_file (char *)\n";
	  cout << "\t--label\n";
	  cout << "\t--labelp[os]           string     (char *)\n";
	  cout << "\t--lat[itude]           degrees    (float) \n";
	  cout << "\t--loc[altime]          time       (float) \n";
	  cout << "\t--lon[gitude]          degrees    (float) \n";
	  cout << "\t--marker_[file]        filename   (char *)\n";
	  cout << "\t--markers\n";
	  cout << "\t--me[rcator]\n";
	  cout << "\t--mo[onside]\n";
	  cout << "\t--night_[image]        image_file (char *)\n";
	  cout << "\t--nights[ide]\n";
	  cout << "\t--no[transparency]\n";
	  cout << "\t--ob[server]           lon,lat    (float, float)\n";
	  cout << "\t--or[thographic]\n";
	  cout << "\t--ou[tput]             filename   (char *)\n";
	  cout << "\t--rad[ius]             percent    (int)\n";
	  cout << "\t--rand[om]\n";
	  cout << "\t--rang[e]              range      (float) \n";
	  cout << "\t--roo[t]\n";
	  cout << "\t--rot[ate]             degrees    (float)\n";
	  cout << "\t--sh[ade]              percent    (int)\n";
	  cout << "\t--st[ar_den]           density    (float)\n";
	  cout << "\t--su[nrel]     del_lon,del_lat    (float, float)\n";
	  cout << "\t--sw[ap]\n";
	  cout << "\t--v[ersion]\n";
	  cout << "\t--w[indow]\n";
	  cout << "\nCharacters inside the square braces are optional\n";
	  exit (EXIT_SUCCESS);
	}
      else if (strncmp (argv[i],"--version",3) == 0) 
	{
	  cout << versionstring << endl;
	  cout << "For more information, see " 
	       << "http://www.alumni.caltech.edu/~hari/xplanet\n";
	  exit (EXIT_SUCCESS);
	}	    
      else if (strncmp (argv[i],"--animate",3) == 0) 
	{
	  opts.display = ANIMATE;
	  opts.mode = MERCATOR;
	}
      else if (strncmp (argv[i],"--background",4) == 0) 
	{
	  i++;
	  if (i >= argc) usage ("missing argument to --background");
	  opts.background = new char[strlen (argv[i]) + 1];
	  strcpy (opts.background, argv[i]);
	  opts.mode = ORTHOGRAPHIC;
	}	  
      else if (strncmp (argv[i],"--blend",4) == 0) 
	{
	  opts.blend = 1;
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--body",4) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --body");
	  sscanf (argv[i], "%d", &opts.body);
	  if (opts.body < 0 ) 
	    {
	      opts.body = random() % 5;
	    }
	  else if (opts.body > 4)
	    {
	      cerr << "Body number " << opts.body << " is not valid.\n"
		   << "Using earth (body 0)\n";
	      opts.body = 0;
	    }

	  // Moon and Mercury are airless, disable terminator shading
	  if (opts.body == 1 || opts.body == 3) opts.fuzz = 0;

	}
      else if (strncmp (argv[i],"--center",4) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --center");
	  sscanf (argv[i], "%d,%d", &opts.centx, &opts.centy);
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--cloud_image",4) == 0) 
	{
	  i++;
	  if (i >= argc) usage ("missing argument to --cloud_image");
	  opts.cloud = new char[strlen (argv[i]) + 1];
	  strcpy (opts.cloud, argv[i]);
	}	  
      else if (strncmp (argv[i],"--color",4) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --color");
	  opts.color = new char[strlen (argv[i]) + 1];
	  strcpy (opts.color, argv[i]);
	}
      else if (strncmp (argv[i],"--date",5) == 0)
	{
	  i++;
#ifdef HAVE_STRPTIME
	  if (i >= argc) usage("missing argument to --date");
	  struct tm *tm = gmtime (&opts.time.tv_sec);
	  strptime (argv[i], "%d %b %Y %T", tm);
	  opts.time.tv_sec = mktime (tm);
#else
	  cerr << "This system does not have the strptime function.\n";
	  cerr << "The --date option will be ignored.\n";
#endif
	}
      else if (strncmp (argv[i],"--dayside",5) == 0) 
	{
	  char *view = "Dayside view";
	  opts.title = new char[strlen (view) + 1];
	  strcpy (opts.title, view);
	  opts.fuzz = 0;
	  if (opts.position != FIXED) 
	    cerr << "Setting observer position to dayside\n";
	  opts.position = DAYSIDE;
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--demfile",6) == 0) 
	{
	  i++;
	  if (i >= argc) usage ("missing argument to --demfile");
	  opts.dem = new char[strlen (argv[i]) + 1];
	  strcpy (opts.dem, argv[i]);
	  opts.mode = ORTHOGRAPHIC;
	}	  
      else if (strncmp (argv[i], "--demscale",6) == 0)
	{
	  i++;
	  if (i >= argc) usage ("missing argument to --demscale");
	  sscanf(argv[i], "%f", &opts.demscale);
	  if (opts.demscale > 1) cerr << "Setting demscale to 1\n";
	}
      else if (strncmp (argv[i],"--earthside",3) == 0) 
	{
	  char *view = "View from earth";
	  opts.title = new char[strlen (view) + 1];
	  strcpy (opts.title, view);
	  if (opts.position != FIXED) 
	    cerr << "Setting observer position to earthside\n";
	  opts.position = EARTHSIDE;
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--font",4) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --font");
	  opts.font = new char[strlen (argv[i]) + 1];
	  strcpy (opts.font, argv[i]);
	}
      else if (strncmp (argv[i],"--fuzz",4) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --fuzz");
	  sscanf (argv[i], "%d", &opts.fuzz);
	  if (opts.fuzz < 0)
	    {
	      cerr << "fuzz must be positive\n";
	      exit (EXIT_FAILURE);
	    }
	}
      else if (strcmp (argv[i],"--geometry") == 0)
	{
	  // this is in case we want to pass geometry info to glut
	  strcpy (argv[i],"-geometry");  
	  i++;
	  if (i >= argc) usage("missing argument to --geometry");
	  XParseGeometry (argv[i], &opts.window_x, &opts.window_y, 
			  &opts.window_width, &opts.window_height);
	  // geometry info is valid for ANIMATE, OUTPUT, or WINDOW
	  if (opts.display == ROOT) opts.display = WINDOW;
	}
      else if (strcmp (argv[i],"--grid") == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --grid");
	  sscanf (argv[i], "%d", &opts.grid);
	  if (opts.grid < 0 || opts.grid > 90) 
	    {
	      cerr << "grid frequency must be between 0 and 90\n";
	      exit (EXIT_FAILURE);
	    }
	}
      else if (strncmp (argv[i],"--gridspace",7) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --gridspace");
	  sscanf (argv[i], "%d", &opts.gridspace);
	  if (opts.gridspace < 0)
	    {
	      cerr << "grid spacing must be positive\n";
	      exit (EXIT_FAILURE);
	    }
	  if (opts.grid == 0) opts.grid = 6;
	}
      else if (strncmp (argv[i],"--image",3) == 0) 
	{
	  i++;
	  if (i >= argc) usage ("missing argument to --image");
	  opts.day = new char[strlen (argv[i]) + 1];
	  strcpy (opts.day, argv[i]);
	}
      else if (strcmp (argv[i],"--label") == 0) 
	{
	  opts.label = 1;
	}
      else if (strncmp (argv[i],"--labelpos",8) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --labelpos");
	  opts.label_mask = XParseGeometry (argv[i], &opts.label_x, 
					    &opts.label_y, &opts.temp, 
					    &opts.temp);
	  
	  if (opts.label_mask & (WidthValue | HeightValue))
	    cerr << "width and height supplied in --labelpos will "
		 << "be ignored\n";
	  opts.label = 1;
	}
      else if (strncmp (argv[i],"--latitude",5) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --latitude");
	  sscanf(argv[i], "%f", &opts.obslat);
	  if (opts.obslat < -90 || opts.obslat > 90) {
	    while(opts.obslat < -90) opts.obslat =  -180 - opts.obslat;
	    while(opts.obslat > 90) opts.obslat = 180 - opts.obslat;
	  }
	  opts.obslat *= deg_to_rad;
	  opts.mode = ORTHOGRAPHIC;
	  if (opts.position == SUNREL) opts.dellat = 999;
	}
      else if (strncmp (argv[i],"--localtime",5) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --localtime");
	  sscanf(argv[i], "%f", &opts.localtime);
	  if (opts.localtime < 0 || opts.localtime > 24) {
	    opts.localtime = fmod (opts.localtime, 24.);
	    if (opts.localtime < 0) opts.localtime += 24;
	  }
	}
      else if (strncmp (argv[i],"--longitude",5) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --longitude");
	  sscanf(argv[i], "%f", &opts.obslon);
	  if (opts.obslon < 0 || opts.obslon > 360) {
	    opts.obslon = fmod (opts.obslon, 360.);
	    if (opts.obslon < 0) opts.obslon += 360;
	  }
	  opts.obslon *= deg_to_rad;
	  if (opts.position == SUNREL) opts.dellon = 999;
	}
      else if (strncmp (argv[i],"--marker_file",9) == 0) 
	{
	  i++;
	  if (i >= argc) usage ("missing argument to --marker_file");
	  opts.markerfile = new char[strlen (argv[i]) + 1];
	  strcpy (opts.markerfile, argv[i]);
	  opts.markers = 1;
	}	  
      else if (strncmp (argv[i],"--markers",9) == 0) 
	{
	  opts.markers = 1;
	}
      else if (strncmp (argv[i],"--mercator",4) == 0)
	{
	  opts.mode = MERCATOR;
	}
      else if (strncmp (argv[i],"--moonside",4) == 0) 
	{
	  char *view = "View from the moon";
	  opts.title = new char[strlen (view) + 1];
	  strcpy (opts.title, view);
	  if (opts.position != FIXED) 
	    cerr << "Setting observer position to moonside\n";
	  opts.position = MOONSIDE;
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--night_image",8) == 0)
	{
	  i++;
	  if (i >= argc) usage ("missing argument to --night_image");
	  opts.night = new char[strlen (argv[i]) + 1];
	  strcpy (opts.night,argv[i]);
	}
      else if (strncmp (argv[i],"--nightside",8) == 0) 
	{
	  char *view = "Nightside view";
	  opts.title = new char[strlen (view) + 1];
	  strcpy (opts.title, view);
	  opts.fuzz = 0;
	  if (opts.position != FIXED) 
	    cerr << "Setting observer position to nightside\n";
	  opts.position = NIGHTSIDE;
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--notransparency",4) == 0)
	{
	  opts.trans = 0;
	}
      else if (strncmp (argv[i],"--observer",4) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --observer");
	  sscanf (argv[i], "%f,%f", &opts.obslon, &opts.obslat);
	  if (opts.obslon < 0 || opts.obslon > 360) {
	    opts.obslon = fmod (opts.obslon, 360.);
	    if (opts.obslon < 0) opts.obslon += 360;
	  }
	  opts.obslon *= deg_to_rad;
	  if (opts.obslat < -90 || opts.obslat > 90) {
	    while(opts.obslat < -90) opts.obslat =  -180 - opts.obslat;
	    while(opts.obslat > 90) opts.obslat = 180 - opts.obslat;
	  }
	  opts.obslat *= deg_to_rad;
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--orthographic",4) == 0) 
	{
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--output",4) == 0) 
	{
	  i++;
	  if (i >= argc) usage("missing argument to --output");
	  opts.output = new char[strlen(argv[i])+1];
	  strcpy(opts.output, argv[i]);
	  opts.display = OUTPUT;
	}
      else if (strncmp (argv[i],"--radius",5) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --radius");
	  sscanf (argv[i], "%d", &opts.radius);
	  if (opts.radius < 0) {
	    cerr << "radius must be positive\n";
	    exit (EXIT_FAILURE);
	  }
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--random",6) == 0)
	{
          opts.obslon = random() % 360;
          opts.obslon *= deg_to_rad;
	  // Weight random latitudes towards the equator
	  opts.obslat = (random() % 2000)/1000.0 - 1;
	  opts.obslat = asin (opts.obslat);
          opts.rotate = random() % 360;
          opts.rotate *= deg_to_rad;
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--range",6) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --range");
	  sscanf(argv[i], "%f", &opts.range);
	  if (opts.range <= 1) {
	    cerr << "range must be greater than 1\n";
	  }
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--root",5) == 0) 
	{
	  opts.display = ROOT;
	}
      else if (strncmp (argv[i],"--rotate",5) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --rotate");
	  sscanf(argv[i], "%f", &opts.rotate);
	  if (opts.rotate < 0 || opts.rotate > 360) {
	    opts.rotate = fmod (opts.rotate, 360.);
	    if (opts.rotate < 0) opts.rotate += 360;
	  }
	  opts.rotate *= deg_to_rad;
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--shade",4) == 0)
	{
	  int shade;
	  i++;
	  if (i >= argc) usage("missing argument to --shade");
	  sscanf (argv[i], "%d", &shade);
	  if (shade < 0 || shade > 100) {
	    while (shade < 0) shade += 100;
	    while (shade > 100) shade -= 100;
	    cerr << "shade set to " << shade << "%\n";
	  }
	  opts.shade = shade/100.;
	}
      else if (strncmp (argv[i],"--star_den",4) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --star_den");
	  sscanf (argv[i], "%f", &opts.star_den);
	  if (opts.star_den < 0 || opts.star_den > 1.0) {
	    cerr << "star density must be between 0 and 1\n";
	    exit (EXIT_FAILURE);
	  }
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--sunrel",4) == 0)
	{
	  i++;
	  if (i >= argc) usage("missing argument to --sunrel");
	  sscanf (argv[i], "%f,%f", &opts.dellon, &opts.dellat);
	  opts.dellon *= deg_to_rad;
	  opts.dellat *= deg_to_rad;
	  if (opts.position != FIXED) 
	    cerr << "Setting observer position to sun-relative\n";
	  opts.position = SUNREL;
	  opts.mode = ORTHOGRAPHIC;
	}
      else if (strncmp (argv[i],"--swap",4) == 0)
	{
	  opts.swap = 1;
	}
      else if (strncmp (argv[i],"--window",3) == 0) 
	{
	  opts.display = WINDOW;
	}
      else if (strncmp (argv[i],"--XID",3) == 0) 
	{
	  i++;
	  if (i >= argc) usage("missing argument to --XID");
	  sscanf (argv[i], "%lu", &opts.XID);
	  opts.display = WINDOW;
	}
      else
	{
	  cerr << "unknown option: " << argv[i] << endl;
	  usage(NULL);
	}
    }
}

