/*
 * Options.C
 *
 * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
 *                     University of Berne, Switzerland
 * All rights reserved.
 *
 * This software may be freely copied, modified, and redistributed
 * provided that this copyright notice is preserved on all copies.
 *
 * You may not distribute this software, in whole or in part, as part of
 * any commercial product without the express consent of the authors.
 *
 * There is no warranty or other guarantee of fitness of this software
 * for any purpose.  It is provided solely "as is".
 *
 */

#include <stdlib.h>
#include "Options.h"
#include "Expression.h"
#include "Hull.h"

//___________________________________________________________ Options

static void usage(const rcString&);
Options theOptions;

Options::Options()
: iname("cin"), oname("cout"), optionsForCPP(" "),
  resX(400), resY(400),
  eye(0,1,0), lookat(0,0,0), up(0,0,1), fov(45.0)
{
#ifdef SUPPORT_X11
  drivername = "x11simple";
#else
#ifdef SUPPORT_AMIGA
  drivername = "amigasimple";
#else
  drivername = "example";
#endif
#endif

  verbose        = 0;
  quiet          = 0;
  printlsys      = 0;
  printModules   = 0;
  deleteModules  = 0;
  autoscale      = 1;
  coneSpheres    = 0;
  showHulls      = 0;

  coneResolution   = -1; // use default resolutions
  sphereResolution = -1;

  defaultForward = 10;
  defaultPitch   = dtor(45);
  defaultTurn    = dtor(45);
  defaultRoll    = dtor(45);

  tropismX = NULL;
  tropismY = NULL;
  tropismZ = NULL;
  weight   = NULL;
  hulls    = NULL;
}

void parseOptions(int argc, char** argv)
{
  rcString progname = argv[0];

  while (--argc) {
    argv++;  

    if (argv[0][0] != '-')
      break;

    switch(argv[0][1]) {
    case 'O':
      if (argc < 2) usage(progname);
      theOptions.oname = argv[1];
      argv++;
      argc--;
      break;
    case 'D':
      theOptions.optionsForCPP = theOptions.optionsForCPP 
                                 + " " + argv[0];
      break;
    case 'd':
      if (argc < 2) usage(progname);
      theOptions.drivername = argv[1];
      argv++;
      argc--;
      break;
    case 'v':
      theOptions.verbose = 1;
      break;
    case 'q':
      theOptions.quiet = 1;
      theOptions.verbose = 0;
      theOptions.printlsys = 0;
      theOptions.printModules = 0;
      break;
    case 'l':
      theOptions.printlsys = 1;
      break;
    case 'p':
      theOptions.printModules = 1;
      break;
    case 'e':
      theOptions.deleteModules = 1;
      break;
    case 'R':
      if (argc < 3) usage(progname);
      theOptions.resX = atoi(argv[1]);
      theOptions.resY = atoi(argv[2]);
      argv += 2;
      argc -= 2;
      break;
    case 'E':
      if (argc < 4) usage(progname);
      theOptions.eye = Vector(atof(argv[1]), atof(argv[2]), atof(argv[3]));
      argv += 3;
      argc -= 3;
      theOptions.autoscale = 0;
      break;
    case 'L':
      if (argc < 4) usage(progname);
      theOptions.lookat = Vector(atof(argv[1]), atof(argv[2]), atof(argv[3]));
      argv += 3;
      argc -= 3;
      theOptions.autoscale = 0;
      break;
    case 'U':
      if (argc < 4) usage(progname);
      theOptions.up = Vector(atof(argv[1]), atof(argv[2]), atof(argv[3]));
      argv += 3;
      argc -= 3;
      break;
    case 'f':
      if (argc < 2) usage(progname);
      theOptions.fov = atoi(argv[1]);
      argv += 1;
      argc -= 1;
      break;
    case 'c':
      theOptions.coneSpheres = 1;
      break;
    case 's':
      theOptions.showHulls = 1;
      break;
    case 'h':
      usage(progname);
      break;
    default:
      cerr << "Unrecognized option " << argv[0] << "\n";
      usage(progname);
    }
  }  
  
  if (argc == 1)
    theOptions.iname = argv[0];
  else if (argc < 0 || argc > 1)
    usage(progname);
}

static void usage(const rcString& progname)
{
  cerr << "usage: " << progname << " [options] [filename]\n"
       << "Where options include:\n"
       << "\t-O outfile\t(Set output file name.)\n"
       << "\t-R xres yres\t(Render at given resolution.)\n"
       << "\t-E x y z\t(Set eyepoint vector.)\n"
       << "\t-L x y z\t(Set lookat vector.)\n"
       << "\t-U x y z\t(Set up vector.)\n"
       << "\t-Dname\t\t(Define name as 1 (cpp option).)\n"
       << "\t-Dname=def\t(Define name as \"def\" (cpp option).)\n"
       << "\t-f angle\t(Set field of view.)\n"
       << "\t-d drivername\n"
       << "\t   no\t\t(No turtle interpretation.)\n"
       << "\t   example\t(Example driver.)\n"
       << "\t   bbox\t\t(Calculate bounding box and view parameter.)\n"
       << "\t   rayshade\t(Rayshade driver.)\n"
#ifdef SUPPORT_X11
       << "\t   x11simple\t(Simple line drawing driver for X11.)\n"
       << "\t   x11wire\t(Wire frame driver for X11.)\n"
#endif
#ifdef SUPPORT_AMIGA
       << "\t   amigasimple\t(Simple line drawing driver for AMIGA.)\n"
       << "\t   amigawire\t(Wire frame driver for AMIGA.)\n"
#endif
       << "\t   flat\t\t(Simple z-buffering.)\n"
       << "\t-c\t\t(Toggle cone spheres generation.)\n "
       << "\t-s\t\t(Show defined hulls.)\n "
       << "\t-v\t\t(Verbose output.)\n"
       << "\t-q\t\t(Run quietly.)\n"
       << "\t-l\t\t(Print l-system definition.)\n"
       << "\t-p\t\t(Print resulting module string.)\n"
       << "\t-e\t\t(Erase module after turtle interpretation.)\n"
       << "\t-h\t\t(Print this message.)\n";
        
  exit(1);
}


