# include "opihi.h"

Variable *variables;   /* variable to store the list of all variables */
int      Nvariables;   /* number of currently available variables */

void InitVariables () {
  Nvariables = 0;
  ALLOCATE (variables, Variable, 1); 
}

int set_local_variable (char *name, char *value) {

  int i;
  char *local, *MacroName;

  /* a local variable has the form (macroname).(varname) */
  MacroName = GetMacroName ();

  /* look for global variable (warning or error)
  for (i = 0; i < Nvariables; i++) {
    if (!strcmp (name, variables[i].name)) {
      gprint (GP_ERR, "warning: local variable overrides global name\n");
    }
  } */

  /* look for existing local variable */
  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
  sprintf (local, "%s.%s", MacroName, name);
  for (i = 0; i < Nvariables; i++) {
    if (!strcmp (local, variables[i].name)) {
      free (variables[i].value);
      free (local);
      variables[i].value = strcreate (value);
      return (TRUE);
    }
  }
  /* NEW variable */
  Nvariables ++;
  REALLOCATE (variables, Variable, Nvariables);
  variables[Nvariables - 1].name = local;
  variables[Nvariables - 1].value = strcreate (value);
  return (TRUE);
}

int set_str_variable (char *name, char *value) {

  int i;
  char *local, *MacroName;

  MacroName = GetMacroName ();

  /* look for local variable first */
  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
  sprintf (local, "%s.%s", MacroName, name);
  for (i = 0; i < Nvariables; i++) {
    if (!strcmp (local, variables[i].name)) {
      free (variables[i].value);
      free (local);
      variables[i].value = strcreate (value);
      return (TRUE);
    }
  }
  free (local);

  /* look for global variable */
  for (i = 0; i < Nvariables; i++) {
    if (!strcmp (name, variables[i].name)) {
      free (variables[i].value);
      variables[i].value = strcreate (value);
      return (TRUE);
    }
  }
  /* NEW variable */
  Nvariables ++;
  REALLOCATE (variables, Variable, Nvariables);
  variables[Nvariables - 1].name = strcreate (name);
  variables[Nvariables - 1].value = strcreate (value);
  return (TRUE);
}

int set_variable (char *name, double dvalue) {

  char value[1024];

  sprintf (value, "%.12g", dvalue);
  set_str_variable (name, value);
  return (TRUE);
}

int set_int_variable (char *name, int ivalue) {

  char value[1024];

  sprintf (value, "%d", ivalue);
  set_str_variable (name, value);
  return (TRUE);
}

static char variable_true[] = "1";
static char variable_false[] = "0";

char *get_variable_ptr (char *name) {
  
  int i;
  char *local, *MacroName, *value;

  if (name == NULL) return (NULL);
  if (*name == 0) return (NULL);

  /* check for the existence of the given name (after ?) */
  /* return a string which should not be freed */
  if (*name == '?') {
    value = get_variable_ptr (&name[1]);
    if (value == NULL) {
      return variable_false;
    }
    return variable_true;
  }

  MacroName = GetMacroName ();

  /* look for local variable first */
  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
  sprintf (local, "%s.%s", MacroName, name);
  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
    if (!strcmp(local, variables[i].name)) {
      free (local);
      return (variables[i].value);
    }
  }
  free (local);

  /* look for global variable */
  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
    if (!strcmp(name, variables[i].name)) {
      return (variables[i].value);
    }
  }
  return (NULL);
}

char *get_variable (char *name) {
  
  int i;
  char *local, *MacroName;
  char *value;

  if (name == NULL) return (NULL);
  if (*name == 0) return (NULL);

  /* check for the existence of the given name (after ?) */
  /* return a string which can be freed */
  if (*name == '?') {
    value = get_variable_ptr (&name[1]);
    if (value == NULL) {
      value = strcreate (variable_false);
      return value;
    }
    value = strcreate (variable_true);
    return value;
  }

  MacroName = GetMacroName ();

  /* look for local variable first */
  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
  sprintf (local, "%s.%s", MacroName, name);
  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
    if (!strcmp(local, variables[i].name)) {
      free (local);
      return (strcreate (variables[i].value));
    }
  }
  free (local);

  /* look for global variable */
  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
    if (!strcmp(name, variables[i].name)) {
      return (strcreate (variables[i].value));
    }
  }
  return (NULL);
}

/* return TRUE / FALSE if name is an existant variable */
int get_variable_exists (char *name) {
  
  int i;
  char *local, *MacroName;

  MacroName = GetMacroName ();

  /* look for local variable first */
  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
  sprintf (local, "%s.%s", MacroName, name);
  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
    if (!strcmp(local, variables[i].name)) {
      free (local);
      return (TRUE);
    }
  }
  free (local);

  /* look for global variable */
  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
    if (!strcmp(name, variables[i].name)) {
      return (TRUE);
    }
  }
  return (FALSE);
}

char *get_local_variable_ptr (char *name) {
  
  int i;
  char *local, *MacroName;

  MacroName = GetMacroName ();

  /* look for local variable first */
  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
  sprintf (local, "%s.%s", MacroName, name);
  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
    if (!strcmp(local, variables[i].name)) {
      free (local);
      return (variables[i].value);
    }
  }
  free (local);
  return (NULL);
}

float get_variable_default (char *name, float dvalue) {

  char *value;
  float fvalue;

  value = get_variable (name);
  if (value == NULL) {
    return (dvalue);
  }
  fvalue = atof (value);
  return (fvalue);
}

double get_double_variable (char *name, int *found) {
  
  int i;
  char *local, *MacroName;

  MacroName = GetMacroName ();

  /* look for local variable first */
  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
  sprintf (local, "%s.%s", MacroName, name);
  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
    if (!strcmp(local, variables[i].name)) {
      free (local);
      *found = TRUE;
      return (atof (variables[i].value));
    }
  }
  free (local);

  /* look for global variable */
  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
    if (!strcmp(name, variables[i].name)) {
      *found = TRUE;
      return (atof (variables[i].value));
    }
  }
  *found = FALSE;
  return (0.0);
}

int get_int_variable (char *name, int *found) {
  
  int i;
  char *local, *MacroName;

  MacroName = GetMacroName ();

  /* look for local variable first */
  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
  sprintf (local, "%s.%s", MacroName, name);
  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
    if (!strcmp(local, variables[i].name)) {
      *found = TRUE;
      free (local);
      return (atof (variables[i].value));
    }
  }
  free (local);

  /* look for global variable */
  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
    if (!strcmp(name, variables[i].name)) {
      *found = TRUE;
      return (atof (variables[i].value));
    }
  }
  *found = FALSE;
  return (0.0);
}

int DeleteNamedScalar (char *name) {

  int i, j;

  for (i = 0; i < Nvariables; i++) {
    if (!strcmp (name, variables[i].name)) {
      free (variables[i].name);
      free (variables[i].value);
      for (j = i; j < Nvariables - 1; j++) {
	variables[j] = variables[j + 1];
      }
      Nvariables --;
      REALLOCATE (variables, Variable, MAX (Nvariables, 1));
      return (TRUE);
    }
  }
  return (FALSE);
}

int IsScalar (char *name) { 

  int i;

  for (i = 0; i < Nvariables; i++) {
    if (!strcmp (name, variables[i].name)) return (TRUE);
  }
  return (FALSE);
}

void ListVariables () {

  int i;

  if (Nvariables == 0) {
    gprint (GP_ERR, "No defined variables\n");
    return;
  }

  for (i = 0; i < Nvariables; i++) {
    gprint (GP_ERR, "%s = %s\n", variables[i].name, variables[i].value);
  }
  return;
}

int SelectScalar (char *string, double *value) {

  char *end;

  /* if string is a number, return TRUE */
  *value = strtod (string, &end);
  if (end == string + strlen(string)) return (TRUE);

  return (FALSE);
}
