/*===========================================================================
  Copyright (C) 1993-2009 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* .IDENT       lnedflux.c                                 */
/* .AUTHORS     Pascal Ballester (ESO/Garching)            */
/*              Cristian Levin   (ESO/La Silla)            */
/* .KEYWORDS    Spectroscopy, Long-Slit                    */
/* .PURPOSE                                                */
/* .VERSION     1.0  Package Creation  17-MAR-1993 

    090728	last modif			           */
/* ------------------------------------------------------- */

#include <stdio.h>
#include <math.h>

#include <midas_def.h>

#include <gl_defs.h>
#include <main_defs.h>
#include <spec_defs.h>
#include <agl_defs.h>

#define MINWAVE		-99999.0
#define MAXWAVE		99999.0
#define MINY		-99999.0
#define MAXY		99999.0
#define DBORDER		10.0
#define NPOINTS		500

#define MAXDEL		80		/* max. temp. deleted points */

/* Keywords */
char Resptab[MAXLINE];

/* structures for allocating column values of 'RESPTAB' */
float *Wave, *Ratio;
int *Row;	/* row number associated to each value */

int  	NumLine;		/* Number of rows read from 'RESPTAB' */

int	DelList[MAXDEL];	/* List of temporarily deleted points */
int	NumDel = 0;		/* DelList[] cardinality */

char	DevErase[80], DevNoErase[80];

struct column_ids {
	int wave, ratio;
} Col;



extern void free_fvector(), free_ivector();
extern int file_exists(), graphwin_exists();

void read_column_ids();
void free_data();
void init_arrays_data();
void read_resp_table();
void init_midas();
void end_midas();
void get_agldev();
void end_graphic();
void init_graphic();

void plot_resp_table();
void plot_delete();

void del_point();
void undel_point();

float *fvector();

int   point_deleted(), *ivector();




int main()
{
    int actval;

    init_midas();
    SCKGETC( "RESPTAB", 1, 20, &actval, Resptab );
    read_resp_table();

    init_graphic(DEV_ERASE);
    AG_SSET("FONT=1");     /* nice font */
    plot_resp_table();
    plot_delete();

    free_data();
    end_graphic();
    end_midas();

return 0;
}

void plot_delete()
{
    float cpx = 0.0, cpy = 0.0;
    int key, valpix;
    int i = 0, min = 0;
    float min_deltax, min_deltay;
    float x[2], y[2], xi, yi;
    char str[80];

    while (1) {
    	min_deltax =  min_deltay = MAXWAVE;

    	AG_VLOC( &cpx, &cpy, &key, &valpix );
    	if ( key == MID_BUT )
	    break;

        AG_SSET( RED_COLOR );
    	for ( i = 0; i < NumLine; i++ ) {
	    xi = Wave[i]; 
	    yi = Ratio[i];
	    if ( fabs((double) cpx - xi) < min_deltax &&
	         fabs((double) cpy - yi) < min_deltay ) {
	       	min_deltax = fabs((double) cpx - xi);
	       	min_deltay = fabs((double) cpx - yi);
		min = i;
	    }
	}
	x[0] = Wave[min]; 
	y[0] = Ratio[min];
	if ( point_deleted(min) ) {
            AG_SSET( BLUE_COLOR );
	    undel_point(min);
	    sprintf(str, "point added   : %10.3f %10.5f", x[0], y[0]);
	}
	else {
	    del_point(min);
	    sprintf(str, "point deleted : %10.3f %10.5f", x[0], y[0]);
	}
	SCTPUT(str);
    	AG_GPLM( x, y, 1, CROSS_MARKER );
    	AG_VUPD();
        AG_SSET( DEF_COLOR );
    }
}

void del_point(n)
int n;
{
    int id;
    int unselect = FALSE;

    DelList[NumDel++] = n;

    TCTOPN( Resptab, F_IO_MODE, &id );
    TCSPUT(id, Row[n], &unselect);
    TCTCLO(id);
}

void undel_point(n)
int n;
{
    int i, id;
    int select = TRUE;

    for ( i = 0; i < NumDel; i++ )
	if ( n == DelList[i] ) {
	    DelList[i] = DelList[NumDel-1];
    	    TCTOPN( Resptab, F_IO_MODE, &id );
    	    TCSPUT(id, Row[n], &select);
    	    TCTCLO(id);
	    NumDel--;
	    return;
	}
}

int point_deleted(n)
int n;
{
    int i;

    for ( i = 0; i < NumDel; i++ )
	if ( n == DelList[i] )
	    return( TRUE );
    return( FALSE );
}

void plot_resp_table()
{
    int i, n = 0;
    int ndel = 0;
    float *xdel, *ydel;
    float xmin = MAXWAVE, xmax = MINWAVE;
    float ymin = MAXY, ymax = MINY;
    float *x, *y;
    char options[MAXOPTS];

    /*** get the values to plot ***/

    x = fvector( 0, NumLine-1 );
    y = fvector( 0, NumLine-1 );
    xdel = fvector( 0, NumLine-1 );
    ydel = fvector( 0, NumLine-1 );

    for ( i = 0; i < NumLine; i++ ) {
	if ( !point_deleted(i) ) {
	    x[n] = Wave[i];
	    y[n] = Ratio[i];
	    if ( x[n] < xmin ) xmin = x[n];
	    if ( x[n] > xmax ) xmax = x[n];
	    if ( y[n] < ymin ) ymin = y[n];
	    if ( y[n] > ymax ) ymax = y[n];
	    n++;
	}
	else {
	    xdel[ndel] = Wave[i];
	    ydel[ndel] = Ratio[i];
	    if ( xdel[ndel] < xmin ) xmin = xdel[ndel];
	    if ( xdel[ndel] > xmax ) xmax = xdel[ndel];
	    if ( ydel[ndel] < ymin ) ymin = ydel[ndel];
	    if ( ydel[ndel] > ymax ) ymax = ydel[ndel];
	    ndel++;
        }
    }

    /*** plot... ***/

    /* let's give a border for a nicer plot */
    xmin -= fabs( (double) (xmax - xmin) / DBORDER );
    xmax += fabs( (double) (xmax - xmin) / DBORDER );
    ymin -= fabs( (double) (ymax - ymin) / DBORDER );
    ymax += fabs( (double) (ymax - ymin) / DBORDER );

    strcpy( options, "LABY=RATIO;LABX=WAVE (Angstrom)" );
    AG_AXES( xmin, xmax, ymin, ymax, options );
    
    /* Plot the points */
    AG_SSET( BLUE_COLOR );
    AG_GPLM( x, y, n, CROSS_MARKER );
    AG_VUPD();
    AG_SSET( DEF_COLOR );

    /* Plot the deleted points */
    if ( ndel > 0 ) {
    	AG_SSET( RED_COLOR );
    	AG_GPLM( xdel, ydel, ndel, CROSS_MARKER );
    	AG_VUPD();
    	AG_SSET( DEF_COLOR );
    }

    free_fvector( x, 0, NumLine-1 );
    free_fvector( y, 0, NumLine-1 );
    free_fvector( xdel, 0, NumLine-1 );
    free_fvector( ydel, 0, NumLine-1 );
}

/*******************************************************************
 * read_resp_table(): reads :WAVE and :RATIO columns of 'RESPTAB',
 *******************************************************************/
void read_resp_table()
{
    int  nulval, sortcol, aw, ar, ncols, nrows;
    int i, id, selected; 

    NumLine = NumDel = 0;

    if ( !file_exists( Resptab, ".tbl" ) ) {
	SCTPUT( "*** Integration process has not been performed ***" );
	end_midas();
    }
    TCTOPN( Resptab, F_IO_MODE, &id );
    read_column_ids( id );

    TCIGET( id, &ncols, &nrows, &sortcol, &aw, &ar );
    
    init_arrays_data( nrows );

    for ( i = 1; i <= nrows; i++ ) {
        TCSGET(id, i, &selected);
	TCERDR( id, i, Col.wave, &Wave[NumLine], &nulval );
	TCERDR( id, i, Col.ratio, &Ratio[NumLine], &nulval );
	if ( !selected )
    	    DelList[NumDel++] = NumLine;
	Row[NumLine] = i;
	NumLine++;
    }
    TCTCLO(id);
}

void init_arrays_data( n )
int n;
{

    /* allocate space for data */
    Row   = ivector( 0, n-1 );
    Wave  = fvector( 0, n-1 );
    Ratio = fvector( 0, n-1 );
}

void free_data( n )
{
    free_ivector( Row, 0, n-1 );
    free_fvector( Wave, 0, n-1 );
    free_fvector( Ratio, 0, n-1 );
}

void read_column_ids( id )
int id;
{
    TCCSER( id, ":WAVE",    &Col.wave );
    TCCSER( id, ":RATIO",   &Col.ratio );

    if ( Col.wave == -1 || Col.ratio == -1 ) {
	SCTPUT( "*** Response table is not valid ***" );
	end_midas();
    }
}

void init_midas()
{
    SCSPRO("LNERFL");
}

void end_midas()
{
    SCSEPI();
}


void init_graphic( devtype )
int devtype;
{
    if ( !graphwin_exists() ) {
	SCTPUT( "*** Please create the graphic window ***" );
	end_midas();
    }

    get_agldev();
    switch ( devtype ) {
	case DEV_ERASE:
    		AG_VDEF( DevErase, 0.05, 1.0, 0.0, 1.0, 0.0, 0.0 );
		break;
	case DEV_NO_ERASE:
    		AG_VDEF( DevNoErase, 0.05, 1.0, 0.0, 1.0, 0.0, 0.0 );
		break;
    }
}

void end_graphic()
{
    if ( graphwin_exists() )
    	AG_CLS();
}

/*********************************************************
 * get_agldev(): translate IDI device to devices erasable
 * and non-erasable suitable for AG_VDEF calls.
 *********************************************************/
void get_agldev()
{
    char device[21];	/* name of assoc. device as in pltdevices.dat */

    strcpy( device, "GRAPH_WND0" );

    /* now make the AGL device names */
    strcpy( DevErase, device ); 
    strcat( DevErase, ":" ); /* see AG_VDEF definition */

    strcpy( DevNoErase, device ); 
    strcat( DevNoErase, "/n:" ); /* see AG_VDEF definition */
}
 
