# include "addstar.h"
# define D_NSTARS 1000
# define BYTES_STAR 66
# define BLOCK 1000
#include <sys/time.h>
#include <time.h>

Stars *gstars (file, NSTARS, image) 
char file[];
int *NSTARS;
Image *image;
{

  FILE *f;
  Header header;
  int j, N, Ninstar;
  int nbytes, Nbytes;
  Stars *stars;
  char *buffer, *c, *c2, photcode[64];
  double tmp;
  int done, doneread, Nskip, Nextra, itmp;
  unsigned short int Nc;

  if (!fits_read_header (file, &header)) {
    fprintf (stderr, "ERROR: can't read header for %s\n", file);
    exit (1);
  }

  /* open file */
  f = fopen (file, "r");
  if (f == NULL) {
    fprintf (stderr, "ERROR: can't read data from %s\n", file);
    exit (1);
  }
  fseek (f, header.size, SEEK_SET); 

  /* find image rootname */
  c = strrchr (file, 0x2f);
  if (c == (char *) NULL) {
    strcpy (image[0].name, file);
  } else { 
    strcpy (image[0].name, (c+1));
  }

  /* get astrometry information */
  if (!GetCoords (&image[0].coords, &header)) {
    fprintf (stderr, "ERROR: no astrometric solution in header\n");
    exit (1);
  }
  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
  itmp = 0;
  fits_scan (&header, "NASTRO",   "%d", 1, &itmp);
  if ((itmp == 0) && !ACCEPT_ASTROM) {
    fprintf (stderr, "ERROR: bad astrometric solution in header\n");
    exit (1);
  }
    
  /* CERROR in data file is in arcsec */
  if (!fits_scan (&header, "CERROR",   "%lf", 1, &tmp)) tmp = 1.0;
  image[0].cerror = tmp * 50.0;
  fits_scan (&header, "NAXIS1",   "%hd", 1, &image[0].NX); 
  fits_scan (&header, "NAXIS2",   "%hd", 1, &image[0].NY);
 
  /* get photcode from header */
  if (thiscode == NULL) {
    fits_scan (&header, "PHOTCODE", "%s", 1, photcode);
    thiscode = GetPhotcodebyName (photcode);
  }
  if (thiscode == NULL) {
    fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", photcode);
    exit (1);
  }
  image[0].source = thiscode[0].code;

  image[0].NX -= XOVERSCAN;
  image[0].NY -= YOVERSCAN;
  fits_scan (&header, ExptimeKeyword,  "%lf", 1, &tmp);
  image[0].exptime = tmp;
  
  tmp = 0;
  /* fits_scan (&header, "APMIFIT",  "%lf", 1, &tmp); */
  image[0].apmifit = tmp * 1000.0;

  tmp = 0;
  /* fits_scan (&header, "dAPMIFIT", "%lf", 1, &tmp); */
  image[0].dapmifit = tmp * 1000.0;

  tmp = 0;
  fits_scan (&header, "FLIMIT",   "%lf", 1, &tmp);
  image[0].detection_limit = tmp * 10.0;

  tmp = 0;
  fits_scan (&header, "FSATUR",   "%lf", 1, &tmp);
  image[0].saturation_limit = tmp * 10.0;

  tmp = 0;
  fits_scan (&header, "FWHM_X",   "%lf", 1, &tmp);
  image[0].fwhm_x = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;

  tmp = 0;
  fits_scan (&header, "FWHM_Y",   "%lf", 1, &tmp);
  image[0].fwhm_y = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;

  if (!fits_scan (&header, "TZERO",   "%d",  1, &image[0].tzero)) {
    image[0].tzero = parse_time (&header);
  }

  tmp = 0;
  fits_scan (&header, "TRATE",   "%lf", 1, &tmp);
  image[0].trate = 10000 * tmp;

  tmp = 0;
  fits_scan (&header, AirmassKeyword, "%lf", 1, &tmp);
  image[0].secz = MIN (NO_MAG, 1000*tmp);

  if (!fits_scan (&header, CCDNumKeyword, "%d", 1, &itmp)) {
    image[0].ccdnum = 0xff;
  } else {
    image[0].ccdnum = itmp;
  }

  fits_scan (&header, "ZERO_PT", "%lf", 1, &ZeroPt);

  /* secz is in units milli-airmass */
  image[0].Mcal = 0.0;
  image[0].code = 0;
  image[0].Xm   = NO_MAG;
  bzero (image[0].dummy, sizeof(image[0].dummy));

  /* find expected number of stars */
  fits_scan (&header, "NSTARS", "%d", 1, &image[0].nstar);
  if (image[0].nstar == 0) {
    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
    exit (1);
  }
  ALLOCATE (stars, Stars, image[0].nstar);

  /* load in stars by blocks of 1000 */
  N = 0;
  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR) + 1);
  buffer[BLOCK*BYTES_STAR] = 0;
  Nextra = 0;
  doneread = FALSE;
  while (!doneread) {
    Nbytes = BYTES_STAR * BLOCK - Nextra;
    nbytes = Fread (&buffer[Nextra], 1, Nbytes, f, "char");
    if (nbytes == 0) {
      doneread = TRUE;
      continue;
    }
    nbytes += Nextra;
    /* check line-by-line integrity */
    c = buffer;
    done = FALSE;
    while ((c < buffer + nbytes) && (!done)) { 
      for (c2 = c; *c2 == '\n'; c2++);
      if (c2 > c) { /* extra return chars */
	memmove (c, c2, (int)(buffer + nbytes - c2));
	Nskip = c2 - c;
	nbytes -= Nskip;
	bzero (buffer + nbytes, Nskip);
	if (VERBOSE) fprintf (stderr, "deleted %d extra return chars\n", Nskip);
      }
      c2 = strchr (c, '\n');
      if (c2 == (char *) NULL) {
	done = TRUE;	
	continue;
      }
      c2++;
      if ((c2 - c) != BYTES_STAR) { /* bad line, delete it */
	memmove (c, c2, (int)(buffer + nbytes - c2));
	Nskip = c2 - c;
	nbytes -= Nskip;
	bzero (buffer + nbytes, Nskip);
	if (VERBOSE) fprintf (stderr, "deleted line, %d extra chars\n", Nskip);
      } else {
	c = c2;
      }
    }
    Ninstar = nbytes / BYTES_STAR;
    Nextra = nbytes % BYTES_STAR;
    for (j = 0; j < Ninstar; j++, N++) {
      dparse (&stars[N].X,  1, &buffer[j*BYTES_STAR]);
      dparse (&stars[N].Y,  2, &buffer[j*BYTES_STAR]);
      dparse (&stars[N].M,  3, &buffer[j*BYTES_STAR]);
      dparse (&stars[N].dM, 4, &buffer[j*BYTES_STAR]);
      /* allow for some dynamic filtering of star list */
      if (stars[N].dM > 1000.0 / SNLIMIT) { N--; continue; }
      if (XMAX && (stars[N].X > XMAX))    { N--; continue; }
      if (XMIN && (stars[N].X < XMIN))    { N--; continue; }
      if (YMAX && (stars[N].Y > YMAX))    { N--; continue; }
      if (YMIN && (stars[N].Y < YMIN))    { N--; continue; }

      dparse (&tmp,         5, &buffer[j*BYTES_STAR]);
      stars[N].dophot = tmp;
      dparse (&stars[N].Mgal, 7, &buffer[j*BYTES_STAR]);
      dparse (&stars[N].Map,  8, &buffer[j*BYTES_STAR]);
      dparse (&stars[N].fx,   9, &buffer[j*BYTES_STAR]);
      dparse (&stars[N].fy,  10, &buffer[j*BYTES_STAR]);
      dparse (&stars[N].df,  11, &buffer[j*BYTES_STAR]);

      XY_to_RD (&stars[N].R, &stars[N].D, stars[N].X, stars[N].Y, &image[0].coords);
      while (stars[N].R < 0.0) stars[N].R += 360.0;
      while (stars[N].R >= 360.0) stars[N].R -= 360.0;
      stars[N].found = -1;
    }
  }

  image[0].nstar = N;
  REALLOCATE (stars, Stars, image[0].nstar);
  if (VERBOSE) fprintf (stderr, "read %d stars from target file\n", image[0].nstar);
  *NSTARS = image[0].nstar;

  return (stars);
}




# if (0)
  /* left over fraction of a block */
  nbytes = Fread (buffer, 1, (Nbytes % (BLOCK*BYTES_STAR)), f, "char");
  if (nbytes != (Nbytes % (BLOCK*BYTES_STAR))) {
    fprintf (stderr, "ERROR: failed to read in stars (2)\n");
    exit (1);
  }
  /* check line-by-line integrity */
  Nnew = 0;
  c = buffer;
  done = FALSE;
  while ((c < buffer + nbytes) && (!done)) { 
    for (c2 = c; *c2 == '\n'; c2++);
    if (c2 > c) { /* extra return chars */
      memmove (c, c2, (int)(buffer + nbytes - c2));
      Nnew += c2 - c;
      fprintf (stderr, "deleting %d extra return chars\n", (int)(c2-c));
    }
    c2 = strchr (c, '\n');
    if (c2 == (char *) NULL) {
      if (Nnew > 0) {
	nnew = Fread (&buffer[nbytes-Nnew], 1, Nnew, f, "char");
	if (nnew != Nnew) {
	  fprintf (stderr, "ERROR: failed to read in stars (1)\n");
	  exit (1);
	}
      } else {
	done = TRUE;	
      }
      continue;
    }
    c2++;
    if ((c2 - c) != BYTES_STAR) {
      /* this is a bad line, delete it, adjust data in buffer, 
	 and be ready to read the rest of the last line */
      memmove (c, c2, (int)(buffer + nbytes - c2));
      Nnew += c2 - c;
      fprintf (stderr, "deleting bad line with %d chars\n", (int)(c2-c));
    } else {
      c = c2;
    }
  }
  for (j = 0; j < nbytes / BYTES_STAR; j++, nstar++, N++) {
    dparse (&stars[N].X, 1, &buffer[j*BYTES_STAR]);
    dparse (&stars[N].Y, 2, &buffer[j*BYTES_STAR]);
    dparse (&stars[N].M, 3, &buffer[j*BYTES_STAR]);
    dparse (&stars[N].dM, 4, &buffer[j*BYTES_STAR]);
    XY_to_RD (&stars[N].R, &stars[N].D, stars[N].X, stars[N].Y, &image[0].coords);
    while (stars[N].R < 0.0) stars[N].R += 360.0;
    while (stars[N].R >= 360.0) stars[N].R -= 360.0;
    dparse (&tmp, 5, &buffer[j*BYTES_STAR]);
    stars[N].dophot = tmp;
    stars[N].found = -1;
  }

# endif
