/*                                                                           *
 *   This file is part of the ESO X-shooter Pipeline                         *
 *   Copyright (C) 2006 European Southern Observatory                        *
 *                                                                           *
 *   This library 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, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA    *
 *                                                                           */

/*
 * $Author: amodigli $
 * $Date: 2013-04-26 10:44:44 $
 * $Revision: 1.15 $
 * $Name: not supported by cvs2svn $
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

/*---------------------------------------------------------------------------*/
/**
 * @defgroup xsh_data_grid Grid
 * @ingroup data_handling
 */
/*---------------------------------------------------------------------------*/

/**@{*/


/*-----------------------------------------------------------------------------
                                 Includes
 ----------------------------------------------------------------------------*/

#include <xsh_data_grid.h>
#include <xsh_utils.h>
#include <xsh_error.h>
#include <xsh_msg.h>
#include <xsh_pfits.h>
#include <cpl.h>

/*----------------------------------------------------------------------------
                                 Function implementation
 ----------------------------------------------------------------------------*/

static int xsh_grid_point_compare(const void* one, const void* two){
  xsh_grid_point** a = NULL;
  xsh_grid_point** b = NULL;
  int xa, ya, xb, yb;
                                                                                                                                                             
  a = (xsh_grid_point**) one;
  b = (xsh_grid_point**) two;
                                                                                                                                                             
  xa = (*a)->x;
  xb = (*b)->x;

  ya = (*a)->y;
  yb = (*b)->y;
                                                                                                                                                             
  if (ya < yb)
    return -1;
  else if ( (ya == yb) && (xa <= xb) ){
    return -1;
  }
  else{
    return 1;
  }                                                                                                                                                          
}


/****************************************************************************/
/** 
 * @brief Dump main info about a grid
 * @param grid pointer
 */
/****************************************************************************/
void xsh_grid_dump( xsh_grid* grid)
{
  int i = 0;

  /* check input parameters */
  XSH_ASSURE_NOT_NULL(grid);

  xsh_msg( "Grid  dump" ) ;
  xsh_msg( "Size: %d", grid->size ) ;
  xsh_msg( "Elts: %d", grid->idx ) ;
  for(i =0  ; i<grid->idx ; i++ ) {
    xsh_msg( "x %d y %d v %f", grid->list[i]->x, grid->list[i]->y ,
      grid->list[i]->v) ;
  }
  
  cleanup:
    return;
}


/****************************************************************************/
/** 
 * @brief Dump main info about a grid
 * @param grid pointer
 */
/****************************************************************************/
cpl_table* xsh_grid2table( xsh_grid* grid)
{
  int i = 0;
  cpl_table* tab=NULL;
  double* px=NULL;
  double* py=NULL;
  double* pi=NULL;
  double* pe=NULL;
  //double* pf=NULL;
  //double* pr=NULL;

  int nrows=0;

  /* check input parameters */
  XSH_ASSURE_NOT_NULL(grid);


  nrows= grid->idx;
  tab=cpl_table_new(nrows);
  cpl_table_new_column(tab,"X",CPL_TYPE_DOUBLE);
  cpl_table_new_column(tab,"Y",CPL_TYPE_DOUBLE);
  cpl_table_new_column(tab,"INT",CPL_TYPE_DOUBLE);
  cpl_table_new_column(tab,"ERR",CPL_TYPE_DOUBLE);

  cpl_table_fill_column_window(tab,"X",0,nrows,-1);
  cpl_table_fill_column_window(tab,"Y",0,nrows,-1);
  cpl_table_fill_column_window(tab,"INT",0,nrows,-1);
  cpl_table_fill_column_window(tab,"ERR",0,nrows,-1);

  px=cpl_table_get_data_double(tab,"X");
  py=cpl_table_get_data_double(tab,"Y");
  pi=cpl_table_get_data_double(tab,"INT");
  pe=cpl_table_get_data_double(tab,"ERR");

  for (i = 0; i < nrows; i++) {
    px[i] = grid->list[i]->x;
    py[i] = grid->list[i]->y;
    pi[i] = grid->list[i]->v;
    pe[i] = grid->list[i]->errs;
  }

  cleanup:
    return tab;
}

/****************************************************************************/
/** 
 * @brief Create a grid
 * @param size size of the grid
 * @return the grid structure
 */
/****************************************************************************/
xsh_grid* xsh_grid_create(int size){
  xsh_grid* grid = NULL;

  /* check input parameters */
  XSH_ASSURE_NOT_ILLEGAL(size > 0);
  XSH_CALLOC(grid,xsh_grid,1);
  
  grid->size = size;
  grid->idx = 0;
  XSH_CALLOC(grid->list, xsh_grid_point*, size);

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      xsh_grid_free(&grid);
    }
    return grid;
}



/****************************************************************************/
/** 
 * @brief Free a grid
 * @param grid the grid pointer
 */
/****************************************************************************/
void xsh_grid_free(xsh_grid** grid)
{
  int i = 0;

  if (grid && *grid){
    if ( (*grid)->list ){
      for (i=0; i< (*grid)->idx; i++) {
        XSH_FREE( (*grid)->list[i]);
      }
      XSH_FREE( (*grid)->list);
    }
    XSH_FREE(*grid);
  }
}

/****************************************************************************/
/** 
 * @brief add a point to a grid
 * @param grid The grid
 * @param x x coordinate of the point
 * @param y y coordinate of the point
 * @param v value of the point
 */
/****************************************************************************/
void xsh_grid_add(xsh_grid* grid, int x, int y, double data, double errs, int qual)
{
  xsh_grid_point* point = NULL;
  /* check input parameters */
  XSH_ASSURE_NOT_NULL(grid);
  XSH_ASSURE_NOT_ILLEGAL(grid->idx < grid->size);

  XSH_MALLOC(point,xsh_grid_point,1);
  
  point->x = x;
  point->y = y;
  point->v = data;
  point->errs = errs;
  point->qual = qual;

  grid->list[grid->idx] = point;
  grid->idx++;
  cleanup:
    return;
}


/****************************************************************************/
/**
 * @brief sort grid points
 * @param grid The grid
 */
/****************************************************************************/

void xsh_grid_sort(xsh_grid* grid)
{
  /* check input parameters */
  XSH_ASSURE_NOT_NULL(grid);
                                                                                                                                                           
  /* sort by Y and by X after */
  qsort(grid->list,grid->idx, sizeof(xsh_grid_point*),
    xsh_grid_point_compare);
  cleanup:
    return;
}

/****************************************************************************/
/** 
 * @brief get x points from the grid
 * @param grid the grid pointer
 * @param i grid index point
 * @return the x points
 */
/****************************************************************************/
xsh_grid_point* xsh_grid_point_get(xsh_grid* grid, int i)
{
  xsh_grid_point* res = NULL;

  /* check input parameters */
  XSH_ASSURE_NOT_NULL(grid);
  XSH_ASSURE_NOT_ILLEGAL( i < grid->idx);
  res = grid->list[i];

  cleanup:
    return res;
}

/****************************************************************************/
/** 
 * @brief get the number of elements in the grid
 * @param grid the grid pointer
 * @return the number of elements in the grid
 */
/****************************************************************************/
int xsh_grid_get_index(xsh_grid* grid)
{
  int res = 0;

  /* check input parameters */
  XSH_ASSURE_NOT_NULL(grid);
  res = grid->idx;

  cleanup:
    return res;
}
/**@}*/
