/**  File gg_setwin.c
 *  Transcripted from Motif to GTK+ by P. Vincent to
 *   Replace setwin.c
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <gtk/gtk.h>

#include "defines.h"
#include "graphs.h"
#include "utils.h"
#include "noxprotos.h"

#include "gw_list.h"

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

static gint popup_width = 450 ,list_height = 250;

extern GdkColor  bleuciel ,wheat;

static GtkWidget *datasetprop_popup = NULL;
static GtkWidget *datasetop_popup = NULL;
static GtkWidget *sets_liste = NULL;
static GtkWidget *sets_listop = NULL;
static gint nsel ,nselop;
static GtkWidget *setop_popup = NULL;
static gg_SrcDestStructure *setop_srcdest;

static GtkWidget *datatype_item      ,*length_item;
static GtkWidget *comment_item       ,*mw;

static void gg_changetypeCB (GtkTreeSelection *sel ,Gw_list *w);
static void gg_datasetprop_AAC_CB (GtkWidget *w ,gint reponse);
static void gg_datasetop_AAC_CB   (GtkWidget *w ,gint reponse);
static void gg_setop_AAC_CB       (GtkWidget *w ,gint reponse);

static SetsMenu3Struct  *sets_menu3  = NULL;

/*********  D A T A     S E T S ...  *****************/

static char *rows[MAX_SET_COLS+1][7];
static GtkWidget *cells[MAX_SET_COLS+1][7];

static SetsMenu3Struct  *datasets_menu3  = NULL;

static char *collabels[7] = {"  " ,"Min", "at", "Max", "at", "Mean", "Stdev"};

/**
 *  Replace  create_datasetprop_popup    setwin.c   77
 */
void gg_create_datasetprop_popup (void)
{
  GtkWidget *menubar ,*menupane ,*submenupane ,*aux;
  GtkWidget *vb ,*rc;
  int nbtyp ,i ,j;

  if (datasetprop_popup == NULL) {
    datasetprop_popup = gg_CreateAACDialog ("Data set properties" ,gg_datasetprop_AAC_CB
					    ,0 ,0 ,&vb);
    /* Create sets_liste */
    sets_liste = gg_CreateSetChoice ("Select set:" ,GTK_SELECTION_MULTIPLE
				     ,popup_width ,list_height
				     ,gg_changetypeCB
				     ,&sets_menu3
				     ,NULL);

    /* Menubar */
    menubar = gg_CreateMenuBar (vb);
    menupane = gg_CreateMenu (menubar, "File", 'F', FALSE);
    gg_CreateMenuCloseButton (menupane ,datasetprop_popup);
 
    menupane = gg_CreateMenu (menubar, "Edit", 'E', FALSE);
    gg_CreateMenuButton (menupane, "Duplicate"      ,'c' ,sets_liste ,gg_sets_menu3_CB ,MenuDuplicateCB);
    gg_CreateMenuButton (menupane, "Kill data"      ,'c' ,sets_liste ,gg_sets_menu3_CB ,MenuKillDataCB);

    submenupane =  gg_CreateMenu (menupane ,"Edit data" ,'E' ,FALSE);
    gg_CreateMenuButton (submenupane ,"In text editor" ,'e'  ,sets_liste ,gg_sets_menu3_CB ,MenuEditECB);
    aux = gg_CreateMenuButton (submenupane, "In spreadsheet", 's',sets_liste ,gg_sets_menu3_CB ,MenuNewSCB);
    gtk_widget_set_sensitive (aux ,FALSE);

    submenupane =  gg_CreateMenu (menupane ,"Create new" ,'n' ,FALSE);
    gg_CreateMenuButton (submenupane ,"By formula"      ,'f'  ,sets_liste ,gg_sets_menu3_CB ,MenuNewFCB);
    gg_CreateMenuButton (submenupane ,"In text editor" ,'e'  ,sets_liste ,gg_sets_menu3_CB ,MenuEditECB);
    gg_CreateMenuButton (submenupane ,"From block data" ,'b'  ,sets_liste ,gg_sets_menu3_CB ,MenuNewFCB);
    aux = gg_CreateMenuButton (submenupane, "In spreadsheet", 's',sets_liste ,gg_sets_menu3_CB ,MenuNewSCB);
    gtk_widget_set_sensitive (aux ,FALSE);

    gg_CreateMenuSeparator (menupane);
    gg_CreateMenuButton (menupane ,"Set appearance..."   ,'S'  ,NULL ,ge_set_g5compat_CB ,-1);
    gg_CreateMenuButton (menupane ,"Set operations..."   ,'o'  ,NULL ,gg_create_setop_popup_CB ,-1);

    /* Attach sets_liste */
    gtk_box_pack_start_defaults (GTK_BOX (vb) ,sets_liste);

    rc = gg_CreateHContainer (vb);
    menupane =  gg_CreateMenu (menubar ,"Help" ,'H' ,TRUE); 
    nbtyp = NUMBER_OF_SETTYPES;
    datatype_item = gg_combo_fun (rc ,"Type:" ,&nbtyp ,set_types ,0);
 
    length_item  = gg_entry_new (rc ,"Length:" ,6);
    comment_item = gg_entry_new (vb ,"Comment:" ,26);

	mw = gg_tableau (vb ,"Statistics" ,&wheat ,7 ,7); 

	for (i=0; i<(MAX_SET_COLS+1); i++) {
	  for (j=0; j<7; j++) {
	    cells[i][j] = gtk_label_new ("*");
	    gtk_table_attach_defaults (GTK_TABLE(mw) ,cells[i][j] ,j ,j+1 ,i ,i+1);
	  }
	}

	for (i=0; i<7; i++) {
	  gtk_label_set_text (GTK_LABEL(cells[0][i]) ,collabels[i]);
	}

        for (i = 0; i < MAX_SET_COLS; i++) {
	  rows[i+1][0]  = copy_string (NULL, dataset_colname(i));
	  gtk_label_set_text (GTK_LABEL(cells[i+1][0]) ,rows[i+1][0]);
	}
    gtk_widget_show (sets_liste);
  }
  gtk_widget_show_all (datasetprop_popup);
}

/**
 *  Replace  changetypeCB                setwin.c   186
 */
static void gg_changetypeCB (GtkTreeSelection *sel ,Gw_list *list)
{
  gint gno ,setno ,i ,j ,ncols;
  double *datap;
  int imin, imax;
  double dmin, dmax, dmean, dsd;
  char buf[32];

  gno = get_cg ();
  nsel = gtk_tree_selection_count_selected_rows (sel);
  if (nsel  == 1) {
    setno = gw_list_get_first_selected_row_num (list);
    if (is_valid_setno(gno, setno)) {
      gg_setstr (comment_item ,getcomment (gno, setno));
      sprintf(buf, "%d", getsetlength(gno, setno));
      gg_setstr (length_item ,buf);
      ncols = dataset_cols (gno, setno);
      for (i = 1; i < (MAX_SET_COLS+1); i++) {
        datap = getcol (gno, setno, i-1);
 	minmax (datap, getsetlength(gno, setno), &dmin, &dmax, &imin, &imax);
 	stasum (datap, getsetlength(gno, setno), &dmean, &dsd);
	for (j = 1; j < 7; j++) {
	  if (i-1 < ncols) {
	    switch (j) {
	    case 1:
	      sprintf(buf, "%g", dmin);
	      break;
	    case 2:
	      sprintf(buf, "%d", imin);
	      break;
	    case 3:
	      sprintf(buf, "%g", dmax);
	      break;
	    case 4:
	      sprintf(buf, "%d", imax);
	      break;
	    case 5:
	      sprintf(buf, "%g", dmean);
	      break;
	    case 6:
	      sprintf(buf, "%g", dsd);
	      break;
	    default:
	      strcpy(buf, "");
	      break;
	    }
	    rows[i][j] = copy_string (rows[i][j], buf);
          } else {
	    rows[i][j] = copy_string (rows[i][j], "");
          }
	  gtk_label_set_text (GTK_LABEL(cells[i][j]) ,rows[i][j]);
	}
      }
    }

  }
}

/**
 *  Replace  datasetprop_aac_cb          setwin.c   271
 */
static void gg_datasetprop_AAC_CB (GtkWidget *w ,gint reponse)
{
  int type ,len ,gno ,last ,i;
  char *s = NULL;
  gboolean *sel_rows;

  if (reponse == GTK_RESPONSE_ACCEPT || reponse == GTK_RESPONSE_APPLY   ) {
    if (nsel < 1) {
      errmsg ("No set selected");
      return;
    } else {
      type = gg_get_int (datatype_item);
      gg_evalexpri (length_item, &len);
      if (len < 0) {
	errmsg ("Negative set length!");
	return;
      }
      s = copy_string (s ,gg_getstr (comment_item));

      gno = get_cg ();
      sel_rows = malloc (number_of_sets (gno) * sizeof (gboolean));
      gw_list_get_selected_rows (GW_LIST(sets_liste) ,sel_rows ,&last);
      for (i=0; i<=last; i++) {
	if (sel_rows[i]) {
	  set_dataset_type (gno, i, type);
	  setlength        (gno, i, len);
	  setcomment       (gno, i, s);
	}
      }
      xfree (sel_rows);
      gg_update_all_sets_lists ();
      gg_drawgraph ();
    }
  }

  if (reponse == GTK_RESPONSE_ACCEPT || reponse == GTK_RESPONSE_CLOSE) {
    gtk_widget_hide_all (datasetprop_popup);
  }
}

typedef enum {
    DATASETOP_SORT,
    DATASETOP_REVERSE,
    DATASETOP_JOIN,
    DATASETOP_SPLIT,
    DATASETOP_DROP
} gg_dataSetOpType;


/********* D A T A S E T   O P E R A T I O N S ...  *****************/

static GtkWidget *optype_item ,*xy_item ,*up_down_item ,*length_item;
static GtkWidget *start_item ,*stop_item;


static GtkWidget *datasettype_controls[5];

/**
 *  Replace  datasetoptypeCB    setwin.c   438
 */
static void gg_optype_CB (GtkWidget *w ,gpointer p)
{
  int i ,type;

  if (w == NULL) return;
  type = gg_get_int (w);
  for (i = 0; i < 5; i++) {
    if (i == type) {
      gtk_widget_show (datasettype_controls[i]);
    } else {
      gtk_widget_hide (datasettype_controls[i]);
    }
  }
}

/**
 *  Replace  create_datasetop_popup      setwin.c   337
 */
void gg_create_datasetop_popup (void)
{
  GtkWidget *vb ,*rc;

  if (datasetop_popup == NULL) {
    datasetop_popup = gg_CreateAACDialog ("Data set operations" ,gg_datasetop_AAC_CB
					  ,0 ,0 ,&vb);
    
    /* Create and attach sets_listop */
    sets_listop = gg_CreateSetChoice ("Select set:" ,GTK_SELECTION_MULTIPLE
				      ,popup_width ,list_height
				      ,NULL
				      ,&datasets_menu3
				      ,NULL);
    gtk_box_pack_start_defaults (GTK_BOX (vb) ,sets_listop);


    optype_item = gg_combo_new (vb , "Operation type:" ,6
					,"Sort"                     /* DATASETOP_SORT    */
					,"Reverse"                  /* DATASETOP_REVERSE */
					,"Join"                     /* DATASETOP_JOIN    */
					,"Split"                    /* DATASETOP_SPLIT   */
					,"Drop points");            /* DATASETOP_DROP    */

  
    rc = gg_CreateHContainer (vb);
    xy_item      = gg_combo_new (rc ,"Sort on:" ,7
					 ,"X" ,"Y" ,"Y1" ,"Y2" ,"Y3" ,"Y4");
    up_down_item = gg_combo_new (rc ,"Order:" ,3
					 ,"Ascending" ,"Descending");
    datasettype_controls[0] = rc;                          /* sort */
 
    rc = gg_CreateVContainer (vb);
   datasettype_controls[1] = rc;                           /* Reverse */
   datasettype_controls[2] = rc;                           /* Join */

   rc = gg_CreateVContainer (vb);
   length_item = gg_entry_new (rc, "Length:"  , 6);
   datasettype_controls[3] = rc;                           /* Split */

   rc = gg_CreateHContainer (vb);
   start_item  = gg_entry_new (rc, "Start at:", 6);
   stop_item   = gg_entry_new (rc, "Stop at:" , 6);
   datasettype_controls[4] = rc;                           /* Drop points */

   gtk_combo_box_set_active (GTK_COMBO_BOX(optype_item) ,0);
 
   g_signal_connect (datasetop_popup ,"delete-event",G_CALLBACK (gtk_widget_hide) ,NULL);
   g_signal_connect (optype_item     ,"changed"     ,G_CALLBACK (gg_optype_CB) ,NULL);
  }
  gtk_widget_show_all (datasetop_popup);
  gg_optype_CB (optype_item ,NULL);
}

void gg_create_datasetop_popup_CB (GtkWidget *w ,gpointer p)
{
  gg_create_datasetop_popup ();
}

/**
 *  Replace   datasetop_aac_cb     setwin.c   452
 */
static void gg_datasetop_AAC_CB (GtkWidget *w ,gint reponse)
{
  static int son[MAX_SET_COLS] = {DATA_X, DATA_Y, DATA_Y1, DATA_Y2, DATA_Y3, DATA_Y4};
  GtkTreeSelection *sel;
  int i ,j ,last ,gno ,*selset ,optype ,sorton ,stype ,lpart;
  int startno, endno;
  gboolean *selop_rows;

  if (reponse == GTK_RESPONSE_ACCEPT || reponse == GTK_RESPONSE_APPLY) {
    
    sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (GW_LIST(sets_listop)->view));
    nselop = gtk_tree_selection_count_selected_rows (sel);

    if (nselop < 1) {
      errmsg ("No set selected");
      return;
    } else {
      gno = get_cg ();
      selop_rows = malloc (number_of_sets (gno) * sizeof (gboolean));
      selset     = malloc (number_of_sets (gno) * sizeof (int));
      gw_list_get_selected_rows (GW_LIST(sets_listop) ,selop_rows ,&last);
      j = 0;
      for (i = 0; i <= last; i++) {
	if (selop_rows[i]) selset[j] = i;
	j++;
      }
      optype = gg_get_int (optype_item); 
      switch (optype) {
      case DATASETOP_SORT:
	sorton = son[gg_get_int (xy_item)];
	stype  =     gg_get_int (up_down_item);
	for (i = 0; i <= last; i++) {
	  if (selop_rows[i]) do_sort (i, sorton, stype);
	}
	break;
      case DATASETOP_REVERSE:
	for (i = 0; i <= last; i++) {
	  if (selop_rows[i]) reverse_set(gno, i);
	}
	break;
      case DATASETOP_JOIN:
	join_sets (gno, selset, nselop);
	break;
      case DATASETOP_SPLIT:
	gg_evalexpri (length_item, &lpart);
	for (i = 0; i <= last; i++) {
	  if (selop_rows[i]) do_splitsets(gno ,i , lpart);
	}
	break;
      case DATASETOP_DROP:
	gg_evalexpri (start_item, &startno);
	gg_evalexpri (stop_item , &endno);
	for (i = 0; i <= last; i++) {
	  if (selop_rows[i]) do_drop_points(gno, i, startno, endno);
	}
	break;
      }
      xfree(selop_rows);
      xfree(selset);
      gg_update_all_sets_lists ();
      gg_drawgraph ();
    }
  }
  if (reponse == GTK_RESPONSE_ACCEPT || reponse == GTK_RESPONSE_CLOSE) {
    gtk_widget_hide (datasetop_popup);
  }
}


/*********  S E T   O P E R A T I O N S ...  *****************/

#define OPTYPE_COPY 0
#define OPTYPE_MOVE 1
#define OPTYPE_SWAP 2

/**
 *  Replace create_setop_popup          setwin.c   526
 */
void gg_create_setop_popup (void)
{
  GtkWidget *vb;
 
  if (setop_popup == NULL) {
    setop_popup = gg_CreateAACDialog ("Set operations" ,gg_setop_AAC_CB ,0 ,0 ,&vb);
 
    /* Create graphs and sets lists */
    setop_srcdest = gg_CreateSrcDestSelector (vb ,GTK_SELECTION_BROWSE);
    optype_item = gg_combo_new (vb ,"Type of operation:" ,4
					,"Copy"          /* OPTYPE_COPY */
					,"Move"          /* OPTYPE_MOVE */
					,"Swap");        /* OPTYPE_SWAP */
  }
  gtk_widget_show_all (setop_popup);
}

void gg_create_setop_popup_CB (GtkWidget *w ,gpointer p)
{
  gg_create_setop_popup ();
}

/**
 *  Replace   setop_aac_cb        setwin.c   557
 */
static void gg_setop_AAC_CB (GtkWidget *w ,gint reponse)
{
  Gw_list *slist1 ,*slist2;
  int optype ,gno1, gno2 ,ns1 ,ns2 ,set1 ,set2 ,last_s2 ,res ,i;
  gboolean *s2_is_selected;

  if (reponse == GTK_RESPONSE_ACCEPT || reponse == GTK_RESPONSE_APPLY) {
    res = RETURN_SUCCESS;
    optype = gg_get_int (optype_item); 
    if (!gg_GetSingleListChoice (GW_LIST (setop_srcdest->src->graphs)  ,&gno1)) return;
    if (!gg_GetSingleListChoice (GW_LIST (setop_srcdest->dest->graphs) ,&gno2)) return;
    slist1 = GW_LIST (setop_srcdest->src->sets);
    slist2 = GW_LIST (setop_srcdest->dest->sets);
    ns1 = gw_list_count_rows_selected (slist1);
    ns2 = gw_list_count_rows_selected (slist2);
    if (ns1 != 1) {
      errmsg ("Please select single source");
      return;
    } else {
      set1 = gw_list_get_first_selected_row_num (slist1);
      if (optype == OPTYPE_SWAP) {
	if (ns2 != 1) {
	  errmsg ("Swapping must be done between two sets only");
	  return;
	}
	set2 = gw_list_get_first_selected_row_num (slist2);
	do_swapset (gno1 ,set1 ,gno2 ,set2);
      } else {
	if (ns2 == 0) {
	  set2 = nextset (gno2);
	  if (optype == OPTYPE_COPY) {
	    res = do_copyset (gno1 ,set1 ,gno2 ,set2);
	  } else {
	    res = do_moveset (gno1 ,set1 ,gno2 ,set2);
	  }
	} else {
	  s2_is_selected =  g_malloc (number_of_sets(gno2) * sizeof(gboolean));
	  gw_list_get_selected_rows (slist2 ,s2_is_selected ,&last_s2);
	  for (i = 0; i <last_s2 ; i++) {
	    if (s2_is_selected[i]) {
	      if (optype == OPTYPE_COPY) {
		res = do_copyset (gno1 ,set1 ,gno2 ,i);
	      } else if (optype == OPTYPE_MOVE) {
		res = do_moveset (gno1 ,set1 ,gno2 ,i);
	      }
	      if (res == RETURN_FAILURE) {
		g_free (s2_is_selected);
		break;
	      }
	    }
	  }
	  g_free (s2_is_selected);
	}
      }
      if (res == RETURN_FAILURE) {
	errmsg ("Error in operation");
	return;
      }
    }
    gg_update_all ();
    gg_drawgraph ();    
  }

  if (reponse == GTK_RESPONSE_ACCEPT || reponse == GTK_RESPONSE_CLOSE) {
    gtk_widget_hide (setop_popup);
  }
}

/**
 *  Replace  create_leval_frame          setwin.c   678
 */
void gg_create_leval_frame (int gno)
{
  printf ("gg_create_leval_frame A FAIRE\n");
}
