# include <ohana.h>

int   ByteSwap (char *ptr, int size, int nitems, char *type);

# define BYTE_EXCHANGE(X,Y) tmp = byte[X]; byte[X] = byte[Y]; byte[Y] = tmp;
# define SWAP_BYTE(X) \
  tmp = byte[X+0]; byte[X+0] = byte[X+1]; byte[X+1] = tmp;
# define SWAP_WORD(X) \
  tmp = byte[X+0]; byte[X+0] = byte[X+3]; byte[X+3] = tmp; \
  tmp = byte[X+1]; byte[X+1] = byte[X+2]; byte[X+2] = tmp;
# define SWAP_DBLE(X) \
  tmp = byte[X+0]; byte[X+0] = byte[X+7]; byte[X+7] = tmp; \
  tmp = byte[X+1]; byte[X+1] = byte[X+6]; byte[X+6] = tmp; \
  tmp = byte[X+2]; byte[X+2] = byte[X+5]; byte[X+5] = tmp; \
  tmp = byte[X+3]; byte[X+3] = byte[X+4]; byte[X+4] = tmp;

/** this is also used in libautocode/def/common.h -- consolidate **/
# ifdef linux
# define BYTE_SWAP
# endif

# ifdef sid
# define BYTE_SWAP
# endif

# ifdef dec
# define BYTE_SWAP
# endif

/* add other architectures here, ie dec, alpha, etc */ 

int Fread (void *ptr, int size, int nitems, FILE *f, char *type) {

  int valid, status;

  status = fread (ptr, size, nitems, f);

  valid = ByteSwap (ptr, size, nitems, type);

  if (!valid) return (FALSE);
  return (status);
}

int Fwrite (void *ptr, int size, int nitems, FILE *f, char *type) {

  int valid, status;

  valid = ByteSwap (ptr, size, nitems, type);

  if (!valid) return (FALSE);

  status = fwrite (ptr, size, nitems, f);
  return (status);
}

int ByteSwap (char *ptr, int size, int nitems, char *type) {

# ifdef BYTE_SWAP

  int i;
  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, tmp;

  if (!strcmp (type, "char")) return (TRUE);

  if (!strcmp (type, "short")) {
    byte0 = (unsigned char *)ptr;
    byte1 = (unsigned char *)ptr + 1;
    for (i = 0; i < nitems; i++, byte0 += 2, byte1 += 2) {
      tmp = *byte0;
      *byte0 = *byte1;
      *byte1 = tmp;
    }
    return (TRUE);
  }

  if (!strcmp (type, "int") || !strcmp (type, "float")) {
    byte0 = (unsigned char *)ptr;
    byte1 = (unsigned char *)ptr + 1;
    byte2 = (unsigned char *)ptr + 2;
    byte3 = (unsigned char *)ptr + 3;
    for (i = 0; i < nitems; i++, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
      tmp = *byte0;
      *byte0 = *byte3;
      *byte3 = tmp;
      tmp = *byte1;
      *byte1 = *byte2;
      *byte2 = tmp;
    }
    return (TRUE);
  }

  if (!strcmp (type, "double")) {
    byte0 = (unsigned char *)ptr;
    byte1 = (unsigned char *)ptr + 1;
    byte2 = (unsigned char *)ptr + 2;
    byte3 = (unsigned char *)ptr + 3;
    byte4 = (unsigned char *)ptr + 4;
    byte5 = (unsigned char *)ptr + 5;
    byte6 = (unsigned char *)ptr + 6;
    byte7 = (unsigned char *)ptr + 7;
    for (i = 0; i < nitems; i++, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
      tmp = *byte0;
      *byte0 = *byte7;
      *byte7 = tmp;
      tmp = *byte1;
      *byte1 = *byte6;
      *byte6 = tmp;
      tmp = *byte1;
      *byte2 = *byte5;
      *byte5 = tmp;
      tmp = *byte1;
      *byte3 = *byte4;
      *byte4 = tmp;
    }
    return (TRUE);
  }

# if (0) /** now in autocode **/
  if (!strcmp (type, "regimage")) {
    if (size != REGIMAGE_SIZE) {
      fprintf (stderr, "mismatch in type sizes (RegImage) %d vs %d\n", size, REGIMAGE_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += REGIMAGE_SIZE) {
      SWAP_WORD (284); /* exptime */ 
      SWAP_WORD (288); /* airmass */ 
      SWAP_WORD (292); /* sky */     
      SWAP_WORD (296); /* bias */    
      SWAP_WORD (300); /* fwhm */    
      SWAP_WORD (304); /* telfocus */ 
      SWAP_WORD (308); /* xprobe */ 
      SWAP_WORD (312); /* yprobe */ 
      SWAP_WORD (316); /* zprobe */ 
      SWAP_WORD (320); /* dettemp */ 
      SWAP_WORD (324); /* teltemp[0] */ 
      SWAP_WORD (328); /* teltemp[1] */  
      SWAP_WORD (332); /* teltemp[2] */ 
      SWAP_WORD (336); /* teltemp[3] */ 
      SWAP_WORD (340); /* rotangle */
      SWAP_WORD (344); /* ra */      
      SWAP_WORD (348); /* dec */     
      SWAP_WORD (352); /* obstime */ 
      SWAP_WORD (356); /* regtime */  
    }
    return (TRUE);
  }

  if (!strcmp (type, "detreg")) {
    if (size != DETREG_SIZE) {
      fprintf (stderr, "mismatch in type sizes (DetReg) %d vs %d\n", size, DETREG_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += DETREG_SIZE) {
      SWAP_WORD (0);   /* tstart */
      SWAP_WORD (4);   /* tstop */
      SWAP_WORD (8);   /* treg */
      SWAP_WORD (12);  /* exptime */
      SWAP_WORD (16);  /* type */
      SWAP_WORD (20);  /* filter */
      SWAP_WORD (24);  /* ccd */
      SWAP_WORD (28);  /* Nentry */
      SWAP_WORD (32);  /* Norder */
    }
    return (TRUE);
  }

  if (!strcmp (type, "photpars")) {
    if (size != PHOTPARS_SIZE) {
      fprintf (stderr, "mismatch in type sizes (PhotPars) %d vs %d\n", size, PHOTPARS_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += PHOTPARS_SIZE) {
      SWAP_WORD (0);    /* ZP */
      SWAP_WORD (4);    /* ZPo */
      SWAP_WORD (8);    /* dZP */
      SWAP_WORD (12);   /* K */
      SWAP_WORD (16);   /* A */
      SWAP_WORD (20);   /* tstart */
      SWAP_WORD (24);   /* tstop */
      SWAP_BYTE (28);   /* c1 */
      SWAP_BYTE (30);   /* c2 */
      SWAP_BYTE (32);   /* photcode */
      SWAP_WORD (100);   /* Ntime */
      SWAP_WORD (104);   /* Nmeas */
    }
    return (TRUE);
  }

  if (!strcmp (type, "missing")) {
    if (size != MISSING_SIZE) {
      fprintf (stderr, "mismatch in type sizes (Missing) %d vs %d\n", size, MISSING_SIZE);
      return (FALSE);
    }
    byte0 = (unsigned char *)ptr;
    byte1 = (unsigned char *)ptr + 1;
    byte2 = (unsigned char *)ptr + 2;
    byte3 = (unsigned char *)ptr + 3;
    for (i = 0; i < nitems; i++, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
      tmp = *byte0;
      *byte0 = *byte3;
      *byte3 = tmp;
      tmp = *byte1;
      *byte1 = *byte2;
      *byte2 = tmp;
    }
    return (TRUE);
  }

  if (!strcmp (type, "secfilt")) {
    if (size != SECFILT_SIZE) {
      fprintf (stderr, "mismatch in type sizes (SecFilt) %d vs %d\n", size, SECFILT_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *) ptr;
    for (i = 0; i < nitems; i++, byte += SECFILT_SIZE) {
      SWAP_BYTE (0);   /* M */
      SWAP_BYTE (2);   /* Xm */
      SWAP_BYTE (4);   /* dM */
    }
    return (TRUE);
  }

  if (!strcmp (type, "spectrum")) {
    if (size != SPECTRUM_SIZE) {
      fprintf (stderr, "mismatch in type sizes (Spectrum) %d vs %d\n", size, SPECTRUM_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += SPECTRUM_SIZE) {
      SWAP_WORD (0);  /* ra */ 
      SWAP_WORD (4);  /* dec */ 
      SWAP_WORD (8);  /* exptime */ 
      SWAP_WORD (12); /* airmass */ 
      SWAP_WORD (16); /* Ws */ 
      SWAP_WORD (20); /* We */ 
      SWAP_WORD (24); /* dW */ 
      SWAP_WORD (28); /* Nspec */ 
      SWAP_WORD (32); /* obstime */ 
      SWAP_WORD (36); /* regtime */ 
    }
    return (TRUE);
  }

  if (!strcmp (type, "image")) {
    if (size != IMAGE_SIZE) {
      fprintf (stderr, "mismatch in type sizes (Image) %d vs %d\n", size, IMAGE_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += IMAGE_SIZE) {
      SWAP_DBLE (0); /* coords.crval1 */
      SWAP_DBLE (8); /* coords.crval2 */
      for (j = 16; j < 104; j+=4) { /* coords.crpix, delt, pc_ij, polyterms[7][2] */
	SWAP_WORD (j);
      }
      SWAP_WORD (120); /* tzero */
      SWAP_WORD (124); /* nstar */
      for (j = 128; j < 146; j+=2) { /* sec z, NX, NY, apmifit, dapmifit, source, Mcal, dMcal, Xm */
	SWAP_BYTE (j);
      }
      SWAP_WORD (184); /* exptime */
      SWAP_WORD (210); /* order */
      /**** this (210) is an error! (don't fix, replaced with autocode) ****/
      for (j = 212; j < 240; j+=2) {
	SWAP_BYTE (j); /* Mx - Myyy */
      }
    }
    return (TRUE);
  }

# if (PANSTARRS)
  if (!strcmp (type, "average")) {
    if (size != AVERAGE_SIZE) {
      fprintf (stderr, "mismatch in type sizes (Average) %d vs %d\n", size, AVERAGE_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += AVERAGE_SIZE) {
      SWAP_DBLE (0);   /* R */
      SWAP_DBLE (8);   /* D */
      SWAP_BYTE (16);  /* M */
      SWAP_BYTE (18);  /* Nm */
      SWAP_BYTE (20);  /* Nn */
      SWAP_BYTE (22);  /* Xp */
      SWAP_BYTE (24);  /* Xm */
      SWAP_BYTE (26);  /* code */
      SWAP_WORD (28);  /* offset */
      SWAP_WORD (32);  /* missing */
      SWAP_BYTE (36);  /* dM */
      SWAP_BYTE (38);  /* Xg */
    }
    return (TRUE);
  } 
  if (!strcmp (type, "measure")) {
    if (size != MEASURE_SIZE) {
      fprintf (stderr, "mismatch in type sizes (Measure) %d vs %d\n", size, MEASURE_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += MEASURE_SIZE) {
      SWAP_BYTE (0);   /* dR */
      SWAP_BYTE (2);   /* dD */
      SWAP_BYTE (4);   /* M  */
      SWAP_BYTE (6);   /* Mcal */
      SWAP_BYTE (8);   /* Mgal */
      SWAP_BYTE (10);  /* Map  */
      SWAP_BYTE (12);  /* FWx */
      /* 14, 15, 16, 17 - char */
      SWAP_BYTE (18);  /* source */
      SWAP_WORD (20);  /* t */
      SWAP_WORD (24);  /* averef */
      SWAP_BYTE (28);  /* dt */
      SWAP_BYTE (30);  /* flags */
    }
    return (TRUE);
  }

# endif /** PANSTARRS **/


# if (ELIXIR)
  if (!strcmp (type, "average")) {
    if (size != AVERAGE_SIZE) {
      fprintf (stderr, "mismatch in type sizes (Average) %d vs %d\n", size, AVERAGE_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += AVERAGE_SIZE) {
      SWAP_WORD (0);   /* R */
      SWAP_WORD (4);   /* D */
      SWAP_BYTE (8);   /* M */
      SWAP_BYTE (10);  /* Nm */
      SWAP_BYTE (12);  /* Nn */
      SWAP_BYTE (14);  /* Xp */
      SWAP_BYTE (16);  /* Xm */
      SWAP_BYTE (18);  /* code */
      SWAP_WORD (20);  /* offset */
      SWAP_WORD (24);  /* missing */
      SWAP_BYTE (28);  /* dM */
      SWAP_BYTE (30);  /* Xg */
    }
    return (TRUE);
  } 
  if (!strcmp (type, "measure")) {
    if (size != MEASURE_SIZE) {
      fprintf (stderr, "mismatch in type sizes (Measure) %d vs %d\n", size, MEASURE_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += MEASURE_SIZE) {
      SWAP_BYTE (0);   /* dR */
      SWAP_BYTE (2);   /* dD */
      SWAP_BYTE (4);   /* M  */
      SWAP_BYTE (6);   /* Mcal */
      SWAP_BYTE (8);   /* Mgal */
      SWAP_BYTE (10);  /* Map  */
      SWAP_BYTE (12);  /* FWx */
      /* 14, 15, 16, 17 - char */
      SWAP_BYTE (18);  /* source */
      SWAP_WORD (20);  /* t */
      SWAP_WORD (24);  /* averef */
      SWAP_BYTE (28);  /* dt */
      SWAP_BYTE (30);  /* flags */
    }
    return (TRUE);
  }

# endif /** ELIXIR **/


# if (LONEOS)
  if (!strcmp (type, "average")) {
    if (size != OLDAVERAGE_SIZE) {
      fprintf (stderr, "mismatch in type sizes (OldAverage) %d vs %d\n", size, OLDAVERAGE_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += OLDAVERAGE_SIZE) {
      SWAP_WORD (0);   /* R */
      SWAP_WORD (4);   /* D */
      SWAP_BYTE (8);   /* M */
      SWAP_BYTE (10); /* Nm */
      SWAP_BYTE (12); /* Nn */
      SWAP_BYTE (14); /* Xp */
      SWAP_BYTE (16); /* Xm */
      SWAP_BYTE (18); /* code */
      SWAP_WORD (20); /* offset */
      SWAP_WORD (24); /* missing */
    }
    return (TRUE);
  } 
  if (!strcmp (type, "measure")) {
    if (size != OLDMEASURE_SIZE) {
      fprintf (stderr, "mismatch in type sizes (OldMeasure) %d vs %d\n", size, OLDMEASURE_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += OLDMEASURE_SIZE) {
      SWAP_BYTE (0);   /* dR */
      SWAP_BYTE (2);   /* dD */
      SWAP_BYTE (4);   /* M  */
      SWAP_BYTE (6);   /* Mcal */
      SWAP_BYTE (10);  /* source */
      SWAP_WORD (12);  /* t */
      SWAP_WORD (16);  /* average */
    }
    return (TRUE);
  }
# endif /** LONEOS **/

# if (0) /*** others ***/
  if (!strcmp (type, "oldsecfilt")) {
    if (size != OLDSECFILT_SIZE) {
      fprintf (stderr, "mismatch in type sizes (OldSecFilt) %d vs %d\n", size, OLDSECFILT_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *) ptr;
    for (i = 0; i < nitems; i++, byte += OLDSECFILT_SIZE) {
      SWAP_BYTE (0);   /* M */
      SWAP_BYTE (2);   /* Xm */
    }
    return (TRUE);
  }
  if (!strcmp (type, "rufimage")) {
    if (size != RUFIMAGE_SIZE) {
      fprintf (stderr, "mismatch in type sizes (RufImage) %d vs %d\n", size, RUFIMAGE_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += RUFIMAGE_SIZE) {
      SWAP_WORD (0);   /* sky */
      SWAP_WORD (4);   /* bias */
      SWAP_WORD (8);  /* fwhm */
      SWAP_WORD (12); /* exptime */
      SWAP_WORD (16); /* airmass */
      SWAP_WORD (20); /* obstime */
      SWAP_BYTE (24); /* ccdnum */
    }
    return (TRUE);
  }
  if (!strcmp (type, "olddetreg")) {
    if (size != OLDDETREG_SIZE) {
      fprintf (stderr, "mismatch in type sizes (DetReg) %d vs %d\n", size, OLDDETREG_SIZE);
      return (FALSE);
    }
    byte = (unsigned char *)ptr;
    for (i = 0; i < nitems; i++, byte += OLDDETREG_SIZE) {
      SWAP_WORD (0);   /* tstart */
      SWAP_WORD (4);   /* tstop */
      SWAP_WORD (8);   /* treg */
      SWAP_WORD (12);  /* sigma */
      SWAP_WORD (16);  /* clipsigma */
      SWAP_WORD (20);  /* type */
      SWAP_WORD (24);  /* filter */
      SWAP_WORD (28);  /* ccd */
    }
    return (TRUE);
  }
# endif /** others **/
# endif /** now in autocode **/

  fprintf (stderr, "unknown type %s\n", type);
  return (FALSE);

# else

  return (TRUE);

# endif 

}
