/**
 *  File ge_function.c
 *
 *  Manage menu for Q_Function
 */

#include <string.h>
 
#include <math.h>
#include <gtk/gtk.h>

#include "globals.h"

#include "defines.h"

#include "gw_list.h"

#include "utils.h"
#include "parser.h"
#include "noxprotos.h"

#include "gg_gutil.h"
#include "gg_gtkinc.h"
#include "gg_protos.h"
#include "ge_protos.h"
#include "ng_objects.h"

typedef struct {
  GtkWidget *titre_item;
  GtkWidget *fun_typ_item ,*fun_typ_combo;
  GtkWidget *fun_start      ,*fun_stop;
  GtkWidget *nb_item;
  GtkWidget *xy_item[MAX_SET_COLS];
  GtkWidget *xy_box[MAX_SET_COLS] ,*xy_label[MAX_SET_COLS];
} ge_fun_struct;

static ge_fun_struct ui[2];
#define U ui[n]

static void ge_function_type_CB (GtkWidget w ,gpointer p);
static int nscols = 2;

GtkWidget *ge_function_create_menu (GtkWidget *parent ,int n)
{
  GtkWidget *vbox ,*rc;
  int nbtyp ,i;

  gg_set_wait_cursor();
    
    vbox = gg_CreateVContainer (parent);
    U.titre_item   = gg_label_new (vbox ,"Function template"); 
    nbtyp = NUMBER_OF_SETTYPES;
     U.fun_typ_combo  = gg_combo_fun (vbox ,"Set type:" ,&nbtyp ,set_types ,0);
     U.fun_typ_item   = gg_get_w_box ();

    rc = gg_CreateHContainer (vbox);
    U.fun_start = gg_entry_new (rc, "Start:"     ,10);
    U.fun_stop  = gg_entry_new (rc, "Stop:"      ,10);
    U.nb_item   = gg_entry_new (vbox, "Nb points:" ,10);
    
    for (i = 0; i < MAX_SET_COLS; i++) {
      U.xy_item[i] = gg_entry_new (vbox, dataset_colname(i) ,35);
					 //					  ,&(U.xy_box[i]) ,&(U.xy_label[i]) );
      U.xy_box[i]   = gg_get_w_box   ();
      U.xy_label[i] = gg_get_w_label ();
    }


    // Mise au point
    gg_setstr (U.fun_start ,"0.0");
    gg_setstr (U.fun_stop  ,"1.0");
    gg_setstr (U.nb_item   ,"20");
    gg_setstr (U.xy_item[0]   ,"$t");
    gg_setstr (U.xy_item[1]   ,"2 * x^2");

    gtk_widget_show_all (vbox);
    for (i = nscols; i < MAX_SET_COLS; i++) gtk_widget_hide_all (U.xy_box[i]);

    g_signal_connect (U.fun_typ_combo ,"changed" ,G_CALLBACK (ge_function_type_CB) ,NULL);

  gg_unset_wait_cursor();
  return vbox;
}

/**
 *  
 *  Replace  leval_aac_cb          setwin.c   753
 */

void ge_function_create (int gno)
{
  printf ("ge_function_create A FINIR\n");

  int n = 0;
  int i ,type;
  double start, stop;
  double s ,d;
  int npts;
  const char *formula[MAX_SET_COLS];
  int res;
  int setno;
  grarr *t;

  type   = gg_get_int (U.fun_typ_combo);
  nscols = settype_cols (type);

  if (gg_evalexpr (U.fun_start, &start) != RETURN_SUCCESS) {
    errmsg ("Start item undefined");
    return;
  }

  if (gg_evalexpr (U.fun_stop , &stop) != RETURN_SUCCESS) {
    errmsg ("Stop item undefined");
    return;
  }

  if (gg_evalexpri (U.nb_item , &npts) != RETURN_SUCCESS) {
    errmsg ("Number of points undefined");
    return;
  }
  for (i = 0; i < nscols; i++) {
    formula[i] = gg_getstr (U.xy_item[i]);
  }

  t = get_parser_arr_by_name ("$t");
  if (t == NULL) {
    t = define_parser_arr("$t" ,VAR_INTRINSIC);
    if (t == NULL) {
      errmsg("Internal error");
      return;
    }
  }
    
  if (t->length != 0) {
    xfree (t->data);
    t->length = 0;
  }
  t->data = xmalloc (npts * SIZEOF_DOUBLE);
  if (t->data == NULL) return;
  s = (start + stop ) / 2;
  d = (stop  - start) / 2;
  for (i = 0; i < npts; i++) {
    t->data[i] = s + d*((double) (2*i + 1 - npts)/(npts - 1));
  }

  t->length = npts;
    
  setno = nextset  (gno);
  set_dataset_type (gno, setno, type);
  set_set_hidden   (gno, setno, FALSE);
  if (setlength (gno, setno, npts) != RETURN_SUCCESS) {
    killset (gno, setno);
    XCFREE (t->data);
    t->length = 0;
    return;
  }
    
  set_parser_setno (gno, setno);

  for (i = 0; i < nscols; i++) {
    char buf[32], *expr;
        
    /* preparing the expression */
    sprintf (buf, "GRAPH[%d].SET[%d].%s = ", gno, setno, dataset_colname(i));
    expr = copy_string (NULL, buf);
    expr = concat_strings (expr, formula[i]);

    printf ("ge_function_create: %s \n" ,expr);
        
    /* evaluate the expression */
    res = scanner (expr);
        
    xfree (expr);
        
    if (res != RETURN_SUCCESS) {
      killset (gno, setno);
            
      XCFREE(t->data);
      t->length = 0;
            
      return;
    }
  }
    
  XCFREE(t->data);
  t->length = 0;
  obj_tid_make_current (Q_Set ,setno ,Q_Graph ,gno);
}

/**
 *  Callback called when function type is changed
 */
static void ge_function_type_CB (GtkWidget w ,gpointer p)
{
  ge_function_type_update ();
}

void ge_function_type_update (void)
{
  int n = 0;
  int i;
  int typ = gg_get_int (U.fun_typ_combo);
  nscols = settype_cols (typ);

  for (i = 0; i < MAX_SET_COLS; i++) {
    if (i < nscols) {
      gtk_widget_show_all (U.xy_box[i]);
    } else {
      gtk_widget_hide_all (U.xy_box[i]);
    }
  }
}
