# include "data.h"

# define ESCAPE(MSG,...){ gprint (GP_ERR, MSG, __VA_ARGS__); goto error; } 

int reindex (int argc, char **argv) {
  
  int  i, Npts, Nmax;
  Vector *ivec, *ovec, *xvec;

  ivec = ovec = xvec = NULL;
  Npts = 0;

  if (argc != 6) goto usage;
  if (strcmp(argv[2], "=")) goto usage;
  if (strcmp(argv[4], "using")) goto usage;

  if ((ovec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) goto error;
  if ((ivec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) goto error;
  if ((xvec = SelectVector (argv[5], OLDVECTOR, TRUE)) == NULL) goto error;

  if (xvec->type != OPIHI_INT) ESCAPE("%s\n", "index is not an integer?");

  // ovec matches ivec in type and xvec in size (xvec need not have all ivec elements, and may have duplicates
  ResetVector (ovec, ivec->type, xvec[0].Nelements);

  Nmax = ivec[0].Nelements - 1;

  // we have two cases: (ivec == flt or int)
  if (ivec->type == OPIHI_FLT) {
    opihi_flt *vi = ivec[0].elements.Flt;
    opihi_int *vx = xvec[0].elements.Int;
    for (Npts = i = 0; i < xvec[0].Nelements; i++, vx++) {
      if (*vx == -1) continue;
      if (*vx < 0) ESCAPE("unexpected value in index: %d (%d)\n", *vx, i);
      if (*vx > Nmax) ESCAPE("unexpected value in index: %d (%d)\n", *vx, i);
      ovec[0].elements.Flt[Npts] = vi[*vx];
      Npts++;
    }
  }
  if (ivec->type == OPIHI_INT) {
    opihi_int *vi = ivec[0].elements.Int;
    opihi_int *vx = xvec[0].elements.Int;
    for (Npts = i = 0; i < xvec[0].Nelements; i++, vx++) {
      if (*vx == -1) continue;
      if (*vx < 0) ESCAPE("unexpected value in index: %d (%d)\n", *vx, i);
      if (*vx > Nmax) ESCAPE("unexpected value in index: %d (%d)\n", *vx, i);
      ovec[0].elements.Int[Npts] = vi[*vx];
      Npts++;
    }
  }

  // free up unused memory
  ResetVector (ovec, ivec->type, Npts);
  return (TRUE);

error:
  DeleteVector (ovec);
  return (FALSE);

usage:
    gprint (GP_ERR, "USAGE: reindex (out) = (in) using (index)\n");
    gprint (GP_ERR, "  creates a new vectors (out) from (in) based on sequence in (index)\n");
    return (FALSE);
}

