# include "opihi.h"

char *expand_vectors (char *line) {

  char *newline, *tmpline, strValue[128], *val;
  char *L, *N, *p, *q, *p2, *w;
  int n, I, J, size, showLength, NLINE, Noff, isBuffer, inRange;
  float *ptr;
  double f1;
  Vector *vec;
  Buffer *buf;

  if (line == NULL) return (NULL);

  NLINE = MAX (128, strlen(line));
  ALLOCATE (newline, char, NLINE);

  /* look for form fred[stuff] */
  /* skip first word (command) */
  L = nextword (line);
  if (L == NULL) {
    free (newline);
    return (line);
  }

  n = L - line;
  strncpy (newline, line, n);
  N = newline + n;
  while (1) {
    /* find square-bracket pair [..] */
    p = strchr (L, '[');
    q = strchr (L, ']');
    if ((p == NULL) && (q != NULL)) goto dumpline;
    if ((p != NULL) && (q == NULL)) goto dumpline;
    if ((p == NULL) && (q == NULL)) goto dumpline;
    if (p > q) goto dumpline; /* odd state: unmatched pair: ][ */

    /* find vector subscript */
    n = (int) (q - p - 1);
    val = NULL;
    showLength = FALSE;
    if (n == 0) {
      showLength = TRUE;
    } else {
      tmpline = strncreate (p+1, n);
      val = dvomath (1, &tmpline, &size, 0);
      free (tmpline);
      if (val == NULL) goto dumpline; /* not a valid vector subscript */
    }
    I = 0; 
    if (val != NULL) {
      I = atoi (val);
      free (val);
    }      

    /* if a second [..] immediately follows, we are a buffer, not a vector */
    isBuffer = FALSE;
    if (*(q + 1) == '[') {
      p2 = strchr (q + 1, ']');
      if (p2 != NULL) {
	if (showLength) {
	  gprint (GP_ERR, "unsupported : name[][..]\n"); 
	  goto asVector;
	}

	isBuffer = TRUE;

	/* find buffer second subscript */
	n = (int) (p2 - q - 2);
	val = NULL;
	if (n == 0) {
	  gprint (GP_ERR, "unsupported : name[..][]\n"); 
	  isBuffer = FALSE;
	  goto asVector;
	} 
	tmpline = strncreate (q+2, n);
	val = dvomath (1, &tmpline, &size, 0);
	free (tmpline);
	if (val == NULL) {
	  isBuffer = FALSE;
	  goto asVector; /* not a valid vector subscript */
	}
	J = 0; 
	if (val != NULL) {
	  J = atoi (val);
	  free (val);
	}      
      }
      q = p2;
    }

  asVector:
    /* find vector/buffer name */
    for (w = p - 1; (w >= line) && !OHANA_WHITESPACE(*w) && (isalnum(*w) || (*w == ':') || (*w == '_')); w--);
    w ++;
    n = (int)(p - w);
    tmpline = strncreate (w, n);

    if (isBuffer) {
      if ((buf = SelectBuffer (tmpline, OLDBUFFER, TRUE)) == NULL) goto dumpline;

      /* find buffer element */
      inRange = TRUE;
      inRange &= (I <  +1*buf[0].header.Naxis[0]);
      inRange &= (I >= -1*buf[0].header.Naxis[0]);
      inRange &= (J <  +1*buf[0].header.Naxis[1]);
      inRange &= (J >= -1*buf[0].header.Naxis[1]);
      if (!inRange) {
	gprint (GP_ERR, "buffer subscript out of range\n"); 
	goto escape;
      }
      if (I < 0) I += buf[0].header.Naxis[0];
      if (J < 0) J += buf[0].header.Naxis[1];
      ptr = (float *) buf[0].matrix.buffer;
      f1 = ptr[I + J*buf[0].header.Naxis[0]];
    } else {
      if ((vec = SelectVector (tmpline, OLDVECTOR, TRUE)) == NULL) goto dumpline;

      /* find vector element */
      if (showLength) {
	f1 = vec[0].Nelements;
      } else {
	if ((I >= vec[0].Nelements) || (I < -1*vec[0].Nelements)) {
	  gprint (GP_ERR, "vector subscript out of range\n"); 
	  goto escape;
	}
	if (I < 0) I += vec[0].Nelements;
	f1 = vec[0].elements[I];
      }
    }

    free (tmpline);
    if ((int)f1 == f1) 
      snprintf (strValue, 128, "%.0f", f1);
    else
      snprintf (strValue, 128, "%.9g", f1);

    /* interpolate vector element into newline (being accumulated) */
    size = (N - newline) + (w - L) + strlen(strValue);
    if (size >= NLINE) {
      Noff = N - newline;
      NLINE += 128 + strlen(strValue) + (w - L);
      REALLOCATE (newline, char, NLINE);
      N = newline + Noff;
    }

    n = (int) (w - L);
    strncpy (N, L, n);
    N += n;
    n = strlen (strValue);
    strncpy (N, strValue, n);
    N += n;
    L = q + 1;
  }

dumpline:
  size = (N - newline) + strlen(L);
  if (size >= NLINE) {
    Noff = N - newline;
    NLINE += 128 + strlen(L);
    REALLOCATE (newline, char, NLINE);
    N = newline + Noff;
  }

  n = strlen (L);
  strncpy (N, L, n);
  N[n] = 0;
  free (line);
  return (newline);
  
escape:
  free (line);
  free (newline);
  return (NULL);
}

