# include "dvo.h"

/* db image table */
static ImageMetadata *image = NULL;
static off_t Nimage = 0;
static Coords mosaic;
static Coords field;

/* load images based on parameters and region, etc */
int SetImageMetadataSelection (char *filename) {

  image = NULL;
  
  /* field defines a frame with 0,0 at the field center, and 1 arcsec / pixel */
  InitCoords (&field, "DEC--SIN");
  field.cdelt1 = field.cdelt2 = 1.0 / 3600;

  /* mosaic defines a frame with 0,0 at the mosaic center, and 1 arcsec / pixel */
  InitCoords (&mosaic, "DEC--SIN");
  mosaic.cdelt1 = mosaic.cdelt2 = 1.0 / 3600;

  if ((image = ImageMetadataLoad (filename, &Nimage)) == NULL) return (FALSE);

  // sort the images by their imageID for fast searches
  // XXX is this too slow?  do I need to sort an array of pointers?
  sort_image_metadata (image, Nimage);
  return (TRUE);
}

/* free loaded images */
void FreeImageMetadataSelection () {
  if (image != NULL) free(image);
  image = NULL;
  return;
}

ImageMetadata *MatchImageMetadataDVO (unsigned int imageID) { 

  off_t m = match_image_by_ID (image, Nimage, imageID);
  if (m == -1) return (NULL);

  return (&image[m]);
}

Coords *MatchFieldMetadata (unsigned int imageID) { 

  int m;

  m = match_image_by_ID (image, Nimage, imageID);
  if (m == -1) return (NULL);

  // if WRP, return the image, otherwise return NULL
  // if (strcmp(&image[m].coords.ctype[4], "-WRP")) return NULL;
  // return (&image[m].coords);

  field.crval1 = image[m].crval1;
  field.crval2 = image[m].crval2;
  return (&field);
}

// note that this function is called by the dvo clients and uses the 'metadata' table
// generated by the dvo shell for the mosaic images only.
Coords *MatchMosaicMetadata (unsigned int imageID) { 

  int m;

  m = match_image_by_ID (image, Nimage, imageID);
  if (m == -1) return (NULL);

  // if WRP, return the image, otherwise return NULL
  // if (strcmp(&image[m].coords.ctype[4], "-WRP")) return NULL;
  // return (&image[m].coords);

  mosaic.crval1 = image[m].crval1;
  mosaic.crval2 = image[m].crval2;

  // note that image->theta is calculated based on pc1_1, pc1_2 when the metadata file is
  // generated
  mosaic.pc1_1 =  cos(RAD_DEG*image[m].theta);
  mosaic.pc1_2 =  sin(RAD_DEG*image[m].theta);
  mosaic.pc2_2 =  cos(RAD_DEG*image[m].theta);
  mosaic.pc2_1 = -sin(RAD_DEG*image[m].theta);

  return (&mosaic);
}

off_t match_image_by_ID (ImageMetadata *image, off_t Nimage, unsigned int ID) {

  off_t N, Nlo, Nhi, N1, N2;

  /* bracket first value of interest */
  Nlo = 0; Nhi = Nimage;
  while (Nhi - Nlo > 10) {
    N = 0.5*(Nlo + Nhi);
    if (image[N].imageID < ID) {
      Nlo = N;
    } else {
      Nhi = N + 1;
    }
  }
  N1 = Nlo;

  /* bracket last value of interest */
  Nlo = 0; Nhi = Nimage;
  while (Nhi - Nlo > 10) {
    N = 0.5*(Nlo + Nhi);
    if (image[N].imageID > ID) {
      Nhi = N;
    } else {
      Nlo = N - 1;
    }
  }
  N2 = Nhi;

  for (N = N1; N < N2; N++) {
    if (image[N].imageID == ID) return (N);
  }
  return (-1);
}
