# include "addstar.h"

/* read an image header corresponding to a CMF / CMP data block */
// XXX need to pass AddstarClientOptions?
int ReadImageHeader (Header *header, Image *image, int photcode) {

  int Nastro, ccdnum, hour, min, Nx, Ny, haveNx, haveNy;
  double tmp, sec, Cerror, ZeroPt, FWHM_X, FWHM_Y;
  char *c, photname[64], line[80];

  // zero out the entire image structure
  memset (image, 0, sizeof(Image));

  /* get astrometry information */
  if (!GetCoords (&image[0].coords, header)) {
    fprintf (stderr, "no astrometric solution in header\n");
    return (FALSE);
  }
  // XXX currently, image uses an unsigned short for NX,XY. this is rather restrictive
  // and needs to be at least checked.
  haveNx = gfits_scan (header, "NAXIS1",   "%d", 1, &Nx);
  haveNy = gfits_scan (header, "NAXIS2",   "%d", 1, &Ny);

  if (!haveNx && !haveNy) {
      haveNx = gfits_scan (header, "IMNAXIS1",   "%d", 1, &Nx);
      haveNy = gfits_scan (header, "IMNAXIS2",   "%d", 1, &Ny);
  }

  if (!haveNx || !haveNy) {
      fprintf (stderr, "missing image dimensions in header\n");
      return (FALSE);
  }

  if ((Nx < 0) || (Nx > 0xffff)) {
    fprintf (stderr, "WARNING: NX, NY out of range : image boundary will be wrong\n");
  }

  image[0].NX = Nx;
  image[0].NY = Ny;

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

  /* only load astrometry, NAXIS1,2, and time if this is a MOSAIC_PHU (ctype is ....-DIS) */
  if (!strcmp (&image[0].coords.ctype[4], "-DIS")) {
    RegisterMosaic (&image[0].coords);
    return (TRUE);
  }

  /* require Nastro > 0 unless or ACCEPT_ASTROM */
  Nastro = 0;
  gfits_scan (header, "NASTRO", "%d", 1, &Nastro);
  Cerror = 0;
  gfits_scan (header, "CERROR", "%lf", 1, &Cerror);
  FWHM_X = FWHM_Y = 0;
  gfits_scan (header, "FWHM_X", "%lf", 1, &FWHM_X);
  gfits_scan (header, "FWHM_Y", "%lf", 1, &FWHM_Y);
  if (((Nastro == 0) || (Cerror > MAX_CERROR)) && !ACCEPT_ASTROM) {
    fprintf (stderr, "bad astrometric solution in header\n");
    return (FALSE);
  }
  if ((MIN_FWHM_X > 0.01) && (FWHM_X < MIN_FWHM_X)) {
    fprintf (stderr, "bad psf, skipping\n");
    return (FALSE);
  }
  if ((MIN_FWHM_Y > 0.01) && (FWHM_Y < MIN_FWHM_Y)) {
    fprintf (stderr, "bad psf, skipping\n");
    return (FALSE);
  }
  if (!strcmp (&image[0].coords.ctype[4], "-WRP")) {
    if (!isRegisteredMosaic()) {
      fprintf (stderr, "no mosaic for WRP image (use -mosaic)\n");
      return (FALSE);
    }
  } else {
    /* force image to lie in 0-360 range */
    image[0].coords.crval1 = ohana_normalize_angle (image[0].coords.crval1);
  }

  { 
    double R, D;
    /* sanity check on the image coordinates */
    XY_to_RD (&R, &D, 0.5*Nx, 0.5*Ny, &image[0].coords);
    if (!finite(R) || !finite(D)) {
      fprintf (stderr, "corrupted header coordinates, skipping\n");
      return (FALSE);
    }
  }
    
  /* CERROR in data file is in arcsec */
  if (!gfits_scan (header, "CERROR",   "%lf", 1, &tmp)) tmp = 1.0;
  image[0].cerror = tmp * 50.0;
 
  /* get photcode from header */
  if (photcode == 0) {
    if (!gfits_scan (header, "PHOTCODE", "%s", 1, photname)) {
      fprintf (stderr, "photcode not supplied in header\n");
      return (FALSE);
    }
    photcode = GetPhotcodeCodebyName (photname);
    if (photcode == 0) {
      fprintf (stderr, "photcode %s not found in photcode table\n", photname);
      return (FALSE);
    }
  }
  if (photcode == 0) { 
    fprintf (stderr, "no valid photcode is supplied\n");
    return (FALSE);
  }
  image[0].photcode = photcode;

  image[0].NX -= XOVERSCAN;
  image[0].NY -= YOVERSCAN;
  gfits_scan (header, ExptimeKeyword,  "%lf", 1, &tmp);
  image[0].exptime = tmp;
  
  /*** why are we no longer using APMIFIT?? ***/
  tmp = 0;
  /* gfits_scan (header, "APMIFIT",  "%lf", 1, &tmp); */
  image[0].apmifit = tmp;

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

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

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

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

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

  if (STKeyword[0]) {
    /* get ST (used for airmass calculation) */
    gfits_scan (header, STKeyword, "%s", 1, line);
    /* remove ':' characters */
    for (c = strchr (line, ':'); c != (char *) NULL; c = strchr (line, ':')) { *c = ' '; }
    sscanf (line, "%d %d %lf", &hour, &min, &sec);
    image[0].sidtime = hour + min/60.0 + sec/3600.0;
  } else {
    double jd;
    jd = ohana_sec_to_jd (image[0].tzero);
    image[0].sidtime  = ohana_lst (jd, Longitude);
  }
  image[0].latitude = Latitude;

  tmp = 0;
  if (gfits_scan (header, "TRATE",   "%lf", 1, &tmp)) {
    image[0].trate = 10000 * tmp;
  } else {
    image[0].trate = 0.0;
  }

  image[0].secz = NAN;
  if (gfits_scan (header, AirmassKeyword, "%lf", 1, &tmp)) {
    image[0].secz = tmp;
  } 

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

  gfits_scan (header, "ZERO_PT", "%lf", 1, &ZeroPt);
  if (ZeroPt != GetZeroPoint()) {
      fprintf (stderr, "inconsistent zero point values: image: %f, config: %f\n", ZeroPt, GetZeroPoint()); 
      return (FALSE);
  }

  /* secz is in units milli-airmass */
  image[0].Mcal = 0.0;
  image[0].Xm   = NAN_S_SHORT;
  image[0].code = 0;

  /* find expected number of stars */
  if (!gfits_scan (header, "NSTARS", "%d", 1, &image[0].nstar) && !NO_STARS) {
    fprintf (stderr, "can't get NSTARS from header\n");
    return (FALSE);
  }

  return (TRUE);
}
