# include "relphot.h"

RelphotMode args (int argc, char **argv) {

  int N;
  double trange;

  /* define time */
  TimeSelect = FALSE;
  if ((N = get_argument (argc, argv, "-time"))) {
    remove_argument (N, &argc, argv);
    if (!ohana_str_to_time (argv[N], &TSTART)) { 
      fprintf (stderr, "ERROR: syntax error\n");
      return (MODE_ERROR);
    }
    remove_argument (N, &argc, argv);
    if (!ohana_str_to_dtime (argv[N], &trange)) { 
      if (!ohana_str_to_time (argv[N], &TSTOP)) { 
	fprintf (stderr, "ERROR: syntax error\n");
	return (MODE_ERROR);
      }
    } else {
      if (trange < 0) {
	trange = fabs (trange);
	TSTOP = TSTART;
	TSTART -= trange;
      } else {
	TSTOP = TSTART + trange;
      }
    }
    remove_argument (N, &argc, argv);
    TimeSelect = TRUE;
  }

  /* specify portion of the sky */
  UserPatch.Rmin = 0;
  UserPatch.Rmax = 360;
  UserPatch.Dmin = -90;
  UserPatch.Dmax = +90;
  if ((N = get_argument (argc, argv, "-region"))) {
    remove_argument (N, &argc, argv);
    UserPatch.Rmin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    UserPatch.Rmax = atof (argv[N]);
    remove_argument (N, &argc, argv);
    UserPatch.Dmin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    UserPatch.Dmax = atof (argv[N]);
    remove_argument (N, &argc, argv);
  }

  /* specify region file by name (eg n0000/0000.00) */
  UserCatalog = NULL;
  if ((N = get_argument (argc, argv, "-catalog"))) {
    remove_argument (N, &argc, argv);
    UserCatalog = strcreate (argv[N]);
    remove_argument (N, &argc, argv);
  }

  USE_BASIC_CHECK = FALSE;
  if ((N = get_argument (argc, argv, "-basic-image-search"))) {
    remove_argument (N, &argc, argv);
    USE_BASIC_CHECK = TRUE;
  }

  USE_FULL_OVERLAP = TRUE;
  if ((N = get_argument (argc, argv, "-sloppy-image-overlap"))) {
    remove_argument (N, &argc, argv);
    USE_FULL_OVERLAP = FALSE;
  }

  SET_MREL_VERSION = 1;
  if ((N = get_argument (argc, argv, "-set-mrel-version"))) {
    remove_argument (N, &argc, argv);
    SET_MREL_VERSION = atof(argv[N]);
    remove_argument (N, &argc, argv);
  }

  VERBOSE = VERBOSE2 = FALSE;
  if ((N = get_argument (argc, argv, "-v"))) {
    VERBOSE = TRUE;
    remove_argument (N, &argc, argv);
  }
  if ((N = get_argument (argc, argv, "-vv"))) {
    VERBOSE2 = VERBOSE = TRUE;
    remove_argument (N, &argc, argv);
  }

  NTHREADS = 0;
  if ((N = get_argument (argc, argv, "-threads"))) {
    remove_argument (N, &argc, argv);
    NTHREADS = atof (argv[N]);
    remove_argument (N, &argc, argv);
  }

  // XXX for the moment, make this selection manual.  it needs to be automatic 
  // based on the state of the SkyTable
  HOST_ID = 0;
  PARALLEL = FALSE;
  if ((N = get_argument (argc, argv, "-parallel"))) {
    PARALLEL = TRUE;
    remove_argument (N, &argc, argv);
  }
  // this is a test mode : rather than launching the remote jobs and waiting for completion,
  // relphot will simply list the remote command and wait for the user to signal completion
  PARALLEL_MANUAL = FALSE;
  if ((N = get_argument (argc, argv, "-parallel-manual"))) {
    PARALLEL = TRUE; // -parallel-manual implies -parallel
    PARALLEL_MANUAL = TRUE;
    remove_argument (N, &argc, argv);
  }
  // this is a test mode : rather than launching the relphot_client jobs remotely, they are 
  // run in serial via 'system'
  PARALLEL_SERIAL = FALSE;
  if ((N = get_argument (argc, argv, "-parallel-serial"))) {
    if (PARALLEL_MANUAL) {
      fprintf (stderr, "ERROR: cannot mix -parallel-manual and -parallel-serial\n");
      exit (1);
    }
    PARALLEL = TRUE; // -parallel-serial implies -parallel
    PARALLEL_SERIAL = TRUE;
    remove_argument (N, &argc, argv);
  }

  PLOTSTUFF = FALSE;
  if ((N = get_argument (argc, argv, "-plot"))) {
    PLOTSTUFF = TRUE;
    remove_argument (N, &argc, argv);
  }

  PLOTDELAY = 500000;
  if ((N = get_argument (argc, argv, "-plotdelay"))) {
    remove_argument (N, &argc, argv);
    PLOTDELAY = 1e6*atof(argv[N]);
    PLOTSTUFF = TRUE; // always turn on plotting if i request a plot delay
    remove_argument (N, &argc, argv);
  }

  if ((N = get_argument (argc, argv, "-outroot"))) {
    remove_argument (N, &argc, argv);
    OUTROOT = strcreate (argv[N]);
    remove_argument (N, &argc, argv);
  } else {
    OUTROOT = strcreate ("relphot");
  }      

  strcpy (STATMODE, "WT_MEAN");
  if ((N = get_argument (argc, argv, "-statmode"))) {
    remove_argument (N, &argc, argv);
    strcpy (STATMODE, argv[N]);
    remove_argument (N, &argc, argv);
  }

  NLOOP = 8;
  if ((N = get_argument (argc, argv, "-n"))) {
    remove_argument (N, &argc, argv);
    NLOOP = atof (argv[N]);
    remove_argument (N, &argc, argv);
  }
  if ((N = get_argument (argc, argv, "-nloop"))) {
    remove_argument (N, &argc, argv);
    NLOOP = atof (argv[N]);
    remove_argument (N, &argc, argv);
  }

  NGRID = 8;
  if ((N = get_argument (argc, argv, "-ngrid"))) {
    remove_argument (N, &argc, argv);
    NGRID = atof (argv[N]);
    remove_argument (N, &argc, argv);
  }

  RESET = FALSE;
  if ((N = get_argument (argc, argv, "-reset"))) {
    remove_argument (N, &argc, argv);
    RESET = TRUE;
  }

  RESET_ZEROPTS = FALSE;
  if ((N = get_argument (argc, argv, "-reset-zpts"))) {
    remove_argument (N, &argc, argv);
    RESET_ZEROPTS = TRUE;
  }

  UPDATE = FALSE;
  if ((N = get_argument (argc, argv, "-update"))) {
    remove_argument (N, &argc, argv);
    UPDATE = TRUE;
  }

  UPDATE_CATFORMAT = NULL;
  if ((N = get_argument (argc, argv, "-update-catformat"))) {
    remove_argument (N, &argc, argv);
    UPDATE_CATFORMAT = strcreate (argv[N]);
    remove_argument (N, &argc, argv);
  }

  SAVE_IMAGE_UPDATES = TRUE;
  if ((N = get_argument (argc, argv, "-skip-image-updates"))) {
    remove_argument (N, &argc, argv);
    SAVE_IMAGE_UPDATES = FALSE;
  }

  MaxDensityUse = FALSE;
  if ((N = get_argument (argc, argv, "-max-density"))) {
    remove_argument (N, &argc, argv);
    MaxDensityValue = atof(argv[N]);
    remove_argument (N, &argc, argv);
    MaxDensityUse = TRUE;
  }

  CLOUD_TOLERANCE = 0.02;
  if ((N = get_argument (argc, argv, "-cloud-limit"))) {
    remove_argument (N, &argc, argv);
    CLOUD_TOLERANCE = atof(argv[N]);
    remove_argument (N, &argc, argv);
  }

  // XXX should we load a tree from CATDIR by default?
  // NOTE: a given catdir needs an appropriate boundary tree
  BOUNDARY_TREE = NULL;
  if ((N = get_argument (argc, argv, "-boundary-tree"))) {
    remove_argument (N, &argc, argv);
    BOUNDARY_TREE = strcreate(argv[N]);
    load_tess (BOUNDARY_TREE);
    remove_argument (N, &argc, argv);
  }

  SHOW_PARAMS = FALSE;
  if ((N = get_argument (argc, argv, "-params"))) {
    remove_argument (N, &argc, argv);
    SHOW_PARAMS = TRUE;
  }

  PlotMmin = 10.0; PlotMmax = 20.0; PlotdMmin = -1.0; PlotdMmax = 1.0;
  if ((N = get_argument (argc, argv, "-plrange"))) {
    remove_argument (N, &argc, argv);
    PlotMmin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    PlotMmax = atof (argv[N]);
    remove_argument (N, &argc, argv);
    PlotdMmin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    PlotdMmax = atof (argv[N]);
    remove_argument (N, &argc, argv);
  }

  /* XXX this argument used to do two things: specify the camera name and tell the analysis to
     calculate a common zero point for a single mosaic.  I've moved the MOSAICNAME concept into the
     config system, but need to use this argument to specify that the mosaic zeropoints should be
     calculated. */
  MOSAIC_ZEROPT = FALSE;
  if ((N = get_argument (argc, argv, "-mosaic"))) {
    remove_argument (N, &argc, argv);
    MOSAIC_ZEROPT = TRUE;
    if (!strcasecmp (MOSAICNAME, "none")) {
      fprintf (stderr, "mosaic astrometry selected by MOSAICNAME not defined\n");
      exit (2);
    }
  }

  FREEZE_IMAGES = FALSE;
  if ((N = get_argument (argc, argv, "-imfreeze"))) {
    remove_argument (N, &argc, argv);
    FREEZE_IMAGES = TRUE;
  }

  FREEZE_MOSAICS = FALSE;
  if ((N = get_argument (argc, argv, "-mosfreeze"))) {
    remove_argument (N, &argc, argv);
    FREEZE_MOSAICS = TRUE;
  }

  // USE_GRID is not valid for all cases, probably should be its own mode...
  USE_GRID = FALSE;
  if ((N = get_argument (argc, argv, "-grid"))) {
    remove_argument (N, &argc, argv);
    USE_GRID = TRUE;
  }

  KEEP_UBERCAL = TRUE;
  if ((N = get_argument (argc, argv, "-reset-ubercal"))) {
    remove_argument (N, &argc, argv);
    KEEP_UBERCAL = FALSE;
  }

  MIN_ERROR = 0.001;
  if ((N = get_argument (argc, argv, "-minerror"))) {
    remove_argument (N, &argc, argv);
    MIN_ERROR = atof (argv[N]);
    remove_argument (N, &argc, argv);
    /* require MIN_ERROR > 0 */
  }  

  AreaSelect = FALSE;
  if ((N = get_argument (argc, argv, "-area"))) {
    remove_argument (N, &argc, argv);
    AreaXmin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    AreaXmax = atof (argv[N]);
    remove_argument (N, &argc, argv);
    AreaYmin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    AreaYmax = atof (argv[N]);
    remove_argument (N, &argc, argv);
    AreaSelect = TRUE;
  }

  ImagSelect = FALSE;
  if ((N = get_argument (argc, argv, "-instmag"))) {
    remove_argument (N, &argc, argv);
    ImagMin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    ImagMax = atof (argv[N]);
    remove_argument (N, &argc, argv);
    ImagSelect = TRUE;
  }

  DophotSelect = FALSE;
  if ((N = get_argument (argc, argv, "-dophot"))) {
    remove_argument (N, &argc, argv);
    DophotValue = atof (argv[N]);
    remove_argument (N, &argc, argv);
    DophotSelect = TRUE;
  }

  SyntheticPhotometry = FALSE;
  if ((N = get_argument (argc, argv, "-synthphot"))) {
    remove_argument (N, &argc, argv);
    SyntheticPhotometry = TRUE;
    init_synthetic_mags();
  }

  refPhotcode = NULL;
  if ((N = get_argument (argc, argv, "-refcode"))) {
    remove_argument (N, &argc, argv);
    refPhotcode = GetPhotcodebyName (argv[N]);
    if (!refPhotcode) {
      fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", argv[N]);
      exit (1);
    }
    remove_argument (N, &argc, argv);
  }

  REGION_FILE = NULL;
  if ((N = get_argument (argc, argv, "-region-hosts"))) {
    remove_argument (N, &argc, argv);
    REGION_FILE = strcreate (argv[N]);
    remove_argument (N, &argc, argv);
  }

  REGION_HOST_ID = 0;
  if ((N = get_argument (argc, argv, "-region-hostID"))) {
    remove_argument (N, &argc, argv);
    REGION_HOST_ID = atoi (argv[N]);
    remove_argument (N, &argc, argv);
  }

  RelphotMode mode = MODE_ERROR;
  if ((N = get_argument (argc, argv, "-images"))) {
    remove_argument (N, &argc, argv);
    mode = UPDATE_IMAGES;
  }
  if ((N = get_argument (argc, argv, "-averages"))) {
    remove_argument (N, &argc, argv);
    mode = UPDATE_AVERAGES;
  }
  if ((N = get_argument (argc, argv, "-apply-offsets"))) {
    remove_argument (N, &argc, argv);
    mode = APPLY_OFFSETS;
  }
  IMAGE_TABLE = NULL;
  if ((N = get_argument (argc, argv, "-parallel-images"))) {
    remove_argument (N, &argc, argv);
    mode = PARALLEL_IMAGES;
    if (N >= argc) relphot_usage();
    IMAGE_TABLE = strcreate (argv[N]);
    remove_argument (N, &argc, argv);
    if (!REGION_FILE) relphot_usage();
  }

  PARALLEL_REGIONS_MANUAL = FALSE;
  if ((N = get_argument (argc, argv, "-parallel-regions"))) {
    remove_argument (N, &argc, argv);
    mode = PARALLEL_REGIONS;
    if (!REGION_FILE) relphot_usage();
    if ((N = get_argument (argc, argv, "-parallel-regions-manual"))) {
      remove_argument (N, &argc, argv);
      PARALLEL_REGIONS_MANUAL = TRUE;
    }
  }

  switch (mode) {
    case UPDATE_AVERAGES:
      if (argc != 1) relphot_usage();
      break;
      
    case UPDATE_IMAGES:
    case PARALLEL_IMAGES:
    case PARALLEL_REGIONS:
      PhotcodeList = strcreate (argv[1]);
      photcodes = ParsePhotcodeList (PhotcodeList, &Nphotcodes, TRUE); // require SEC photcodes
      remove_argument (1, &argc, argv);
      break;

    default:
      fprintf (stderr, "no valid mode selected\n");
      relphot_usage();
      break;
  }
  if (argc != 1) relphot_usage ();

  return mode;
}

int args_client (int argc, char **argv) {

  int N;
  double trange;

  // by definition, the client is not parallel 
  PARALLEL = FALSE;
  PARALLEL_MANUAL = FALSE;
  PARALLEL_SERIAL = FALSE;

  HOST_ID = 0;
  if ((N = get_argument (argc, argv, "-hostID"))) {
    remove_argument (N, &argc, argv);
    HOST_ID = atoi (argv[N]);
    remove_argument (N, &argc, argv);
  }
  if (!HOST_ID) relphot_client_usage();

  HOSTDIR = NULL;
  if ((N = get_argument (argc, argv, "-hostdir"))) {
    remove_argument (N, &argc, argv);
    HOSTDIR = strcreate (argv[N]);
    remove_argument (N, &argc, argv);
  }
  if (!HOSTDIR) relphot_client_usage();

  IMAGES = NULL; // used in -update mode
  BCATALOG = NULL; // used in -load mode
  MODE = MODE_NONE;
  if ((N = get_argument (argc, argv, "-load"))) {
    MODE = MODE_LOAD;
    remove_argument (N, &argc, argv);
    BCATALOG = strcreate (argv[N]);
    remove_argument (N, &argc, argv);
  }
  if ((N = get_argument (argc, argv, "-update-catalogs"))) {
    if (MODE) {
      fprintf (stderr, "ERROR: cannot mix modes (-load, -update-catalogs, -update-objects)\n");
      relphot_client_usage();
    }
    MODE = MODE_UPDATE;
    remove_argument (N, &argc, argv);
    IMAGES = strcreate (argv[N]);
    remove_argument (N, &argc, argv);
  }
  if ((N = get_argument (argc, argv, "-update-objects"))) {
    if (MODE) {
      fprintf (stderr, "ERROR: cannot mix modes (-load, -update-catalogs, -update-objects)\n");
      relphot_client_usage();
    }
    MODE = MODE_UPDATE_OBJECTS;
    remove_argument (N, &argc, argv);
  }
  if (!MODE) relphot_client_usage();

  strcpy (STATMODE, "WT_MEAN");
  if ((N = get_argument (argc, argv, "-statmode"))) {
    remove_argument (N, &argc, argv);
    strcpy (STATMODE, argv[N]);
    remove_argument (N, &argc, argv);
  }

  BOUNDARY_TREE = NULL;
  if ((N = get_argument (argc, argv, "-boundary-tree"))) {
    remove_argument (N, &argc, argv);
    BOUNDARY_TREE = strcreate(argv[N]);
    load_tess (BOUNDARY_TREE);
    remove_argument (N, &argc, argv);
  }

  /* specify portion of the sky */
  UserPatch.Rmin = 0;
  UserPatch.Rmax = 360;
  UserPatch.Dmin = -90;
  UserPatch.Dmax = +90;
  if ((N = get_argument (argc, argv, "-region"))) {
    remove_argument (N, &argc, argv);
    UserPatch.Rmin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    UserPatch.Rmax = atof (argv[N]);
    remove_argument (N, &argc, argv);
    UserPatch.Dmin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    UserPatch.Dmax = atof (argv[N]);
    remove_argument (N, &argc, argv);
  }

  SET_MREL_VERSION = 1;
  if ((N = get_argument (argc, argv, "-set-mrel-version"))) {
    remove_argument (N, &argc, argv);
    SET_MREL_VERSION = atof(argv[N]);
    remove_argument (N, &argc, argv);
  }

  VERBOSE = VERBOSE2 = FALSE;
  if ((N = get_argument (argc, argv, "-v"))) {
    VERBOSE = TRUE;
    remove_argument (N, &argc, argv);
  }
  if ((N = get_argument (argc, argv, "-vv"))) {
    VERBOSE2 = VERBOSE = TRUE;
    remove_argument (N, &argc, argv);
  }

  RESET = FALSE;
  if ((N = get_argument (argc, argv, "-reset"))) {
    remove_argument (N, &argc, argv);
    RESET = TRUE;
  }

  RESET_ZEROPTS = FALSE;
  if ((N = get_argument (argc, argv, "-reset-zpts"))) {
    remove_argument (N, &argc, argv);
    RESET_ZEROPTS = TRUE;
  }

  KEEP_UBERCAL = TRUE;
  if ((N = get_argument (argc, argv, "-reset-ubercal"))) {
    remove_argument (N, &argc, argv);
    KEEP_UBERCAL = FALSE;
  }

  /* define time */
  TimeSelect = FALSE;
  if ((N = get_argument (argc, argv, "-time"))) {
    remove_argument (N, &argc, argv);
    if (!ohana_str_to_time (argv[N], &TSTART)) { 
      fprintf (stderr, "ERROR: syntax error\n");
      return (FALSE);
    }
    remove_argument (N, &argc, argv);
    if (!ohana_str_to_dtime (argv[N], &trange)) { 
      if (!ohana_str_to_time (argv[N], &TSTOP)) { 
	fprintf (stderr, "ERROR: syntax error\n");
	return (FALSE);
      }
    } else {
      if (trange < 0) {
	trange = fabs (trange);
	TSTOP = TSTART;
	TSTART -= trange;
      } else {
	TSTOP = TSTART + trange;
      }
    }
    remove_argument (N, &argc, argv);
    TimeSelect = TRUE;
  }


  MIN_ERROR = 0.001;
  if ((N = get_argument (argc, argv, "-minerror"))) {
    remove_argument (N, &argc, argv);
    MIN_ERROR = atof (argv[N]);
    remove_argument (N, &argc, argv);
    /* require MIN_ERROR > 0 */
  }  

  UPDATE = FALSE;
  if ((N = get_argument (argc, argv, "-update"))) {
    remove_argument (N, &argc, argv);
    UPDATE = TRUE;
  }

  UPDATE_CATFORMAT = NULL;
  if ((N = get_argument (argc, argv, "-update-catformat"))) {
    remove_argument (N, &argc, argv);
    UPDATE_CATFORMAT = strcreate (argv[N]);
    remove_argument (N, &argc, argv);
  }

  AreaSelect = FALSE;
  if ((N = get_argument (argc, argv, "-area"))) {
    remove_argument (N, &argc, argv);
    AreaXmin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    AreaXmax = atof (argv[N]);
    remove_argument (N, &argc, argv);
    AreaYmin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    AreaYmax = atof (argv[N]);
    remove_argument (N, &argc, argv);
    AreaSelect = TRUE;
  }

  SyntheticPhotometry = FALSE;
  if ((N = get_argument (argc, argv, "-synthphot"))) {
    remove_argument (N, &argc, argv);
    SyntheticPhotometry = FALSE;
    init_synthetic_mags();
  }

  ImagSelect = FALSE;
  if ((N = get_argument (argc, argv, "-instmag"))) {
    remove_argument (N, &argc, argv);
    ImagMin = atof (argv[N]);
    remove_argument (N, &argc, argv);
    ImagMax = atof (argv[N]);
    remove_argument (N, &argc, argv);
    ImagSelect = TRUE;
  }

  DophotSelect = FALSE;
  if ((N = get_argument (argc, argv, "-dophot"))) {
    remove_argument (N, &argc, argv);
    DophotValue = atof (argv[N]);
    remove_argument (N, &argc, argv);
    DophotSelect = TRUE;
  }

  MaxDensityUse = FALSE;
  if ((N = get_argument (argc, argv, "-max-density"))) {
    remove_argument (N, &argc, argv);
    MaxDensityValue = atof(argv[N]);
    remove_argument (N, &argc, argv);
    MaxDensityUse = TRUE;
  }

  if ((MODE == MODE_UPDATE_OBJECTS)  && (argc == 1)) return TRUE;
  if (argc != 2) relphot_client_usage ();

  return TRUE;
}

