/**  File gg_fourier_win.c
 *  Replace fourier transform in gg_compwin.c
 */

#include <gtk/gtk.h>

#include "defines.h"

#include "gw_list.h"

#include "utils.h"

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

#include "fourier.h"


extern GdkColor  bleuciel ,wheat;

static void gg_fourier_AAC_CB (GtkWidget *w ,gint reponse);

static GtkWidget *fourier_win = NULL;
static GtkWidget *vb;
static GtkWidget *but_inverse ,*but_norm    ,*but_complex;
static GtkWidget *but_xscale  ,*but_dumpDC  ,*but_filter;
static GtkWidget *but_padding ,*but_round2n  ,*but_insegmt;
static GtkWidget *but_out_fft  ,*but_outsegmt;
static GtkWidget *dummy_lab;
static gg_SrcDestStructure *srcdest;

void gg_fourier_create_win (GtkWidget *w ,gpointer p)
{
  GtkWidget *fr;
  if (fourier_win == NULL) {
    fourier_win = gg_CreateAACDialog ("Fourier transform" ,gg_fourier_AAC_CB ,0 ,0 ,&vb);
    srcdest    = gg_CreateSrcDestSelector (vb ,GTK_SELECTION_MULTIPLE);

    fr = gg_frame (vb ,"General" ,&wheat ,2 ,2);
    but_out_fft  = gg_combo_new (fr ,"Compute:" ,7                
				 ,"Magnitude" 		     /* FFT_OUTPUT_MAGNITUDE */
				 ,"Phase"           	     /* FFT_OUTPUT_PHASE     */
				 ,"Real part"       	     /* FFT_OUTPUT_RE        */
				 ,"Imaginary part"  	     /* FFT_OUTPUT_IM        */
				 ,"Complex"         	     /* FFT_OUTPUT_REIM      */
				 ,"Complex (A, Phi)");	     /* FFT_OUTPUT_APHI      */
    dummy_lab   = gg_label_new       (fr ," ");
    but_inverse = gg_check_new (fr ,"Backward transform: exp(+)");
    but_norm    = gg_combo_new (fr ,"Normalize:" ,5
				,"None"                      /* FFT_NORM_NONE    */
				,"Symmetric"                 /* FFT_NORM_SYMMETRIC */
				,"Forward"                   /* FFT_NORM_FORWARD   */
				,"Backward");                /* FFT_NORM_BACKWARD  */

    fr = gg_frame (vb ,"Input" ,&bleuciel ,2 ,4);
    but_insegmt = gg_combo_new (fr ,"Input segment" ,3
				,"Index"
				,"[Xmin ,Xmax]");
    but_complex = gg_check_new (fr ,"Complex data");
    but_dumpDC  = gg_check_new (fr ,"Dump DC component");
    dummy_lab   = gg_label_new       (fr ," ");
    but_filter  = gg_combo_new (fr ,"Apply window:" ,9       
				,"None (Rectangular)"	     /* FFT_WINDOW_NONE       */
				,"Triangular"		     /*	FFT_WINDOW_TRIANGULAR */
				,"Parzen"		     /*	FFT_WINDOW_PARZEN     */
				,"Welch"		     /*	FFT_WINDOW_WELCH      */
				,"Hanning"		     /*	FFT_WINDOW_HANNING    */
				,"Hamming"		     /*	FFT_WINDOW_HAMMING    */
				,"Flat top"		     /*	FFT_WINDOW_FLATTOP    */
				,"Blackman");		     /*	FFT_WINDOW_BLACKMAN   */
    but_padding = gg_spin_new (fr ,"Parameter"    ,0.0 ,99.0 ,1.0);
    but_padding = gg_spin_new (fr ,"Zero padding" ,1.0 ,99.0 ,1.0);
    but_round2n = gg_check_new(fr ,"Round to 2^N");

    fr = gg_frame (vb ,"Output" ,&wheat ,2 ,1);
    but_xscale  = gg_combo_new (fr ,"X scale:" ,4
				,"Index"                     /* FFT_XSCALE_INDEX */
				,"Frequency"                 /* FFT_XSCALE_NU    */
				,"Angular frequency");       /* FFT_XSCALE_OMEGA */
    but_outsegmt = gg_combo_new (fr ,"Output segment:" ,4
				 ,"Positive"                 /* FFT_OUTSEGMT_POSITIVE    */
				 ,"Positive half length"     /* FFT_OUTSEGMT_HALF_LENGTH */
				 ,"Centered");               /* FFT_OUTSEGMT_CENTERED    */
    gg_fourier_update ();
  }
  gtk_widget_show_all (fourier_win);
}

void gg_fourier_update (void)
{
  if (fourier_win != NULL) {
    FFTParams p;
    if (fourier_params_get (&p) == RETURN_SUCCESS) {
      gg_set_int  (but_inverse  , p.invflag);
      gg_set_int  (but_xscale   , p.xscale);
      gg_set_int  (but_norm     , p.norm);
      gg_set_int  (but_insegmt  , p.insegmt);
      gg_set_int  (but_complex  , p.complexin);
      gg_set_int  (but_dumpDC   , p.dcdump);
      gg_set_dble (but_padding  , p.oversampling);
      gg_set_int  (but_round2n  , p.round2n);
      gg_set_int  (but_filter   , p.filter);
      gg_set_dble (but_padding  , p.padding);
      gg_set_int  (but_outsegmt , p.outsegmt);
      gg_set_int  (but_out_fft  , p.output);
    }
  }
}

void gg_fourier_AAC_CB (GtkWidget *w ,gint reponse)
{
  FFTParams p;
  static int ns2 = 0;
  int gno1 ,setno1 ,gno2 ,setno2 ,setno22 ,ns1 ,resno ,i ,j;
  gint *sl1 ,*sl2;

  if (reponse == GTK_RESPONSE_ACCEPT || reponse == GTK_RESPONSE_APPLY   ) {
    p.invflag      = gg_get_int (but_inverse);
    p.xscale       = gg_get_int (but_xscale);
    p.norm         = gg_get_int (but_norm);
    p.insegmt      = gg_get_int (but_insegmt);
    p.complexin    = gg_get_int (but_complex);
    p.dcdump       = gg_get_int (but_dumpDC);
    p.oversampling = gg_get_int (but_padding);
    p.round2n      = gg_get_int (but_round2n);
    p.filter       = gg_get_int (but_filter);
    p.padding      = gg_get_int (but_padding);
    p.outsegmt     = gg_get_int (but_outsegmt);
    p.output       = gg_get_int (but_out_fft);
    fourier_params_set (&p);

    ns2 = fourier_nb_out_sets (p.output);
    if (gg_GetSrcDestSettings (srcdest ,SD_NSET2_GIVEN
                               ,&gno1 ,&gno2
                               ,&ns1  ,&ns2
                               ,&sl1  ,&sl2) == RETURN_FAILURE) return;
    j = 0;
    for (i = 0; i < ns1; i++) {
      setno1 = sl1[i];
      setno2 = sl2[j];
      j++;
      if (ns2 == 2) {
	setno22 = sl2[j];
	j++;	
      } else {
	setno22 = -1;
      }
      resno = do_fourier (gno1 ,setno1 ,gno2 ,setno2 ,setno22);
      if (resno != RETURN_SUCCESS) {
        errmsg ("Error in nn_fourier ()");
        break;
      }
    }
    gg_drawgraph ();
    ge_update_explorer ();
    xfree (sl1);
    xfree (sl2);
  }

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