# include "data.h"

int write_vectors (int argc, char **argv) {
  
  int append;
  int i, j, Nvec, Ne, N;
  FILE *f;
  char **fmtlist, *fmttype;
  char *p0, *p1, *p2, *format;
  Vector **vec;

  /* look for format option */
  format = (char *) NULL;
  if ((N = get_argument (argc, argv, "-f"))) {
    remove_argument (N, &argc, argv);
    format = strcreate (argv[N]);
    remove_argument (N, &argc, argv);
  }

  append = FALSE;
  if ((N = get_argument (argc, argv, "-append"))) {
    remove_argument (N, &argc, argv);
    append = TRUE;
  }

  if (argc < 3) {
    gprint (GP_ERR, "USAGE: write [-append] [-f \"format\"] file vector vector ...\n");
    return (FALSE);
  }

  /* open file for outuput */
  if (append) {
      f = fopen (argv[1], "a");
  } else {
      f = fopen (argv[1], "w");
  }
  if (f == (FILE *) NULL) {
    gprint (GP_ERR, "can't open file for write\n");
    return (FALSE);
  }

  /* find number of output vectors */
  Nvec = (argc - 2);
  if (Nvec < 1) {
      gprint (GP_ERR, "USAGE: write (file) vector vector ...\n");
      fclose (f);
  fflush (f);
      return (FALSE);
  }
  ALLOCATE (vec, Vector *, Nvec);

  /* select/check vectors from list */
  for (i = 0; i < Nvec; i++) {
    if ((vec[i] = SelectVector (argv[i + 2], OLDVECTOR, FALSE)) == NULL) {
      gprint (GP_ERR, "unknown vector %s\n", argv[i+2]);
      gprint (GP_ERR, "USAGE: write (file) vector vector ...\n");
      free (vec);
      fclose (f);
  fflush (f);
      return (FALSE);    
    }
  }
  
  /* select vector lengths */
  Ne = vec[0][0].Nelements;
  for (i = 0; i < Nvec; i++) {
    if (vec[0][0].Nelements != Ne) {
      gprint (GP_ERR, "error: vectors must all be the same size\n");
      free (vec);
      fclose (f);
  fflush (f);
      return (FALSE);    
    }
  }

  /* default output format */
  if (format == (char *) NULL) {
    for (i = 0; i < vec[0][0].Nelements; i++) {
      for (j = 0; j < Nvec; j++) {
	if (vec[j][0].type == OPIHI_FLT) {
	  fprintf (f, "%.12g ", vec[j][0].elements.Flt[i]);
	} else {
	  fprintf (f, "%d ", vec[j][0].elements.Int[i]);
	}
      }
      fprintf (f, "\n");
    } 
    fclose (f);
    free (vec);
  fflush (f);
    return (TRUE);
  }

  /* construct an array of format strings */
  ALLOCATE (fmttype, char, Nvec);
  ALLOCATE (fmtlist, char *, Nvec);
  for (i = 0; i < Nvec; i++) {
    ALLOCATE (fmtlist[i], char, 1024);
    bzero (fmtlist[i], 1024);
  }

  p0 = format;
  for (j = 0; j < Nvec; j++) {
    /* find this format character */
    p1 = strchr (p0, '%');
    if (p1 == (char *) NULL) {
      gprint (GP_ERR, "mismatch between format and values\n");
      free (fmttype);
      for (i = 0; i < Nvec; i++) free (fmtlist[i]);
      free (fmtlist);
      free (format);
      fclose (f);
  fflush (f);
      return (FALSE);
    }
    
    /* identify type (%NNNNd %NNNNf) */
    for (p2 = p1 + 1; (*p2 == '.') || (*p2 == '-') || (*p2 == '+') || (*p2 == ' ') || isdigit(*p2); p2++);
    strncpy (fmtlist[j], p0, p2 - p0 + 1);
    switch (*p2) {
      case 'e':
      case 'f':
	fmttype[j] = 'f';
	break;
      case 'd':
      case 'c':
      case 'x':
	fmttype[j] = 'd';
	break;
      default:
	gprint (GP_ERR, "syntax error in format (only e,f,d,c,x allowed)\n");
	return (FALSE);
    }
    p0 = p2 + 1;
  }
  strcat (fmtlist[Nvec-1], p0);
  
  for (i = 0; i < vec[0][0].Nelements; i++) {
    for (j = 0; j < Nvec; j++) {
      if (fmttype[j] == 'd') {
	if (vec[j][0].type == OPIHI_FLT) {
	  fprintf (f, fmtlist[j], (int)(vec[j][0].elements.Flt[i]));
	} else {
	  fprintf (f, fmtlist[j], (int)(vec[j][0].elements.Int[i]));
	}
      } 
      if (fmttype[j] == 'f') {
	if (vec[j][0].type == OPIHI_FLT) {
	  fprintf (f, fmtlist[j], (float)(vec[j][0].elements.Flt[i]));
	} else {
	  fprintf (f, fmtlist[j], (float)(vec[j][0].elements.Int[i]));
	}
      } 
    }
    fprintf (f, "\n");
  }
  fclose (f);
  fflush (f);

  free (fmttype);
  for (i = 0; i < Nvec; i++) free (fmtlist[i]);
  free (fmtlist);
  free (format);
  
  return (TRUE);

}


