# include "addstar.h"

/* these variables are needed by Shutdown */
static FILE *f = (FILE *) NULL;
static int Protect = FALSE;
static int Trapped = FALSE;

/* clean up open / locked files before shutting down */
int Shutdown () {  
  int dbstate;

  Protect = TRUE;
  fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
  fprintf (stderr, "ERROR: addrefs halted\n");
  exit (1);
}

void TrapSignal (int sig) {
    fprintf (stderr, "trapped signal %d, exiting gracefully\n", sig);
    if (sig == 11) {
      fprintf (stderr, "seg fault\n");
      exit (1);
    }
    if (Protect) {
      Trapped = TRUE;
      fprintf (stderr, "blocking until protected sections are clear\n");
      return;
    }
    Shutdown ();
}    

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

  int Nm, Nf, dbstate;
  int i, j, Nstars, Nmissed, Nsubset, *subref;
  Stars *stars, *subset, *gstars(), *find_subset();
  GSCRegion region;
  Catalog catalog;

  SetSignals ();
  args (argc, argv);

  /* load data from file */
  stars = gstars (argv[1], &Nstars);
  if (Nstars == 0) {
    if (VERBOSE) fprintf (stderr, "no stars in data file, skipping\n");
    fprintf (stderr, "SUCCESS\n");
    exit (0);
  }

  check_permissions (ImageCat);
  f = fsetlockfile (ImageCat, 3600.0, LCK_HARD, &dbstate);
  if (f == (FILE *) NULL) { /* don't add to empty catalog */
    fprintf (stderr, "ERROR: can't lock image catalog\n");
    exit (1);
  }
  
  /* put stars in the appropriate db file */
  for (i = 0; i < Nstars; i++) {
    if (stars[i].found != -1) continue;
    gregion (&stars[i], &region);
    check_permissions (region.filename);
    make_backup (region.filename);

    catalog.filename = region.filename;  /* don't free region before catalog! */
    fprintf (stderr, "adding to %s [star %d]\n", region.filename, i);
    
    switch (lock_catalog (&catalog, LCK_XCLD)) {
    case 0:
      fprintf (stderr, "ERROR: can't lock file %s\n", catalog.filename);
      exit (1);
    case 1:
      gcatalog (&catalog); /* load from disk */
      break;
    case 2:
      mkcatalog (&region, &catalog); /* fills in new header info */
      break;
    }
    subset = find_subset (&region, stars, Nstars, &subref, &Nsubset);
    if (VERBOSE) fprintf (stderr, "%d stars in subset for %s\n", Nsubset, region.filename);
    find_matches (&region, subset, Nsubset, &catalog);

    /* protect wcatalog from interrupt signals */
    Protect = TRUE;
    wcatalog (&catalog);
    if (Trapped) Shutdown ();
    Protect = FALSE;
    unlock_catalog (&catalog);

    Nm = 0; Nf = 0;
    for (j = 0; j < Nsubset; j++) {
      stars[subref[j]].found = subset[j].found;
      if (subset[j].found == -2) Nm ++;
      if (subset[j].found >=  0) Nf ++;
    }
    /* found:
       -1 - not yet tried
       -2 - found on previous catalog
       -3 - not found on previous catalog
       +N - found elsewhere
    */
    if (VERBOSE) fprintf (stderr, "found %d stars, skipped %d stars\n", Nf, Nm);
    free (subset);
    free (subref);
  }
  
  for (Nmissed = i = 0; i < Nstars; i++) {
    if (stars[i].found == -1) {
      fprintf (stderr, "%d %f %f %f %f\n", i, stars[i].R, stars[i].D, stars[i].M, stars[i].dM);
      Nmissed ++;
    }
  }
  if (Nmissed) fprintf (stderr, "WARNING: %d stars in image were missed!\n", Nmissed);

  fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
  fprintf (stderr, "SUCCESS\n");
  exit (0);
}

int SetSignals () {

  int i;

  /* disable almost all signal interrupts */
  for (i = 0; i < 36; i++) {
    switch (i) {
      /* can't redirect this signals */
    case SIGKILL:    /* kill -9: cannot be caught or ignored */
    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored */
      /* ignore these signals */
    case SIGCHLD:    /* child halted: ignore */
    case SIGPWR:     /* power failure - why ignore this? */
    case SIGWINCH:   /* window resized */
    case SIGCONT:    /* continue - maintain this action */
    case SIGTSTP:    /* stop signal sent from tty - why ignore? */
    case SIGURG:     /* socket signal, ignore this */
      break;
      
    default:
      signal (i, TrapSignal);
    }
  }
  return (TRUE);
}
