/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set sw=2 sts=2 et cin: */
/*
 * This file is part of the MUSE Instrument Pipeline
 * Copyright (C) 2014 European Southern Observatory
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

/*----------------------------------------------------------------------------*
 *                              Includes                                      *
 *----------------------------------------------------------------------------*/
#include "muse_sky.h"

#include "muse_pfits.h"

/** @addtogroup muse_skysub */
/**@{*/

/*----------------------------------------------------------------------------*/
/**
  @brief  Fill a header with the QC parameters for the sky lines.
  @param  aHeader   header with the QC parameters for the sky lines
  @param  aLines    sky line table
  @param  aPrefix   prefix for the QC keywords

  @error{set CPL_ERROR_NULL_INPUT and return,
         one of the input arguments is NULL}
  @error{set CPL_ERROR_DATA_NOT_FOUND and return,
         aLines does not contain any rows}
 */
/*----------------------------------------------------------------------------*/
void
muse_sky_qc_lines(cpl_propertylist *aHeader, cpl_table *aLines,
                  const char *aPrefix)
{
  if (!aHeader || !aLines || !aPrefix) {
    cpl_error_set(__func__, CPL_ERROR_NULL_INPUT);
    return;
  }
  if (cpl_table_get_nrow(aLines) < 1) {
    cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
    return;
  }

  char keyword[KEYWORD_LENGTH];
  int i, ngroups = cpl_table_get_column_max(aLines, "group") + 1;
  for (i = 0; i < ngroups; i++) {
    cpl_table_unselect_all(aLines);
    cpl_table_or_selected_int(aLines, "group", CPL_EQUAL_TO, i);
    cpl_table *gtable = cpl_table_extract_selected(aLines);
    cpl_size irow;
    cpl_table_get_column_maxpos(gtable, "flux", &irow);
    const char *name = cpl_table_get_string(gtable, "name", irow);
    double wavelength = cpl_table_get_double(gtable, "lambda", irow, NULL),
           flux = cpl_table_get_double(gtable, "flux", irow, NULL);
    snprintf(keyword, KEYWORD_LENGTH, "%s LINE%i NAME", aPrefix, i+1);
    cpl_propertylist_append_string(aHeader, keyword, name);
    snprintf(keyword, KEYWORD_LENGTH, "%s LINE%i AWAV", aPrefix, i+1);
    cpl_propertylist_append_double(aHeader, keyword, wavelength);
    snprintf(keyword, KEYWORD_LENGTH, "%s LINE%i FLUX", aPrefix, i+1);
    if (!isfinite(flux)) {
      /* add obviously wrong value to the header,  *
       * since CFITSIO chokes on NANs and the like */
      cpl_propertylist_append_double(aHeader, keyword, -9999.999);
      cpl_msg_error(__func__, "Sky-line fit failed for group %d, computed "
                    "flux is infinite!", i+1);
    } else {
      cpl_propertylist_append_double(aHeader, keyword, flux);
    }
    cpl_table_delete(gtable);
  } /* for ngroups */
  cpl_table_unselect_all(aLines);
} /* muse_sky_qc_lines() */

/*----------------------------------------------------------------------------*/
/**
  @brief  Fill a header with the QC parameters for the sky continuum.
  @param  aHeader      header to store the QC parameters for the sky continuum
  @param  aContinuum   sky continuum table
  @param  aPrefix      prefix for the QC keywords

  @error{set CPL_ERROR_NULL_INPUT and return,
         one of the input arguments is NULL}
  @error{set CPL_ERROR_DATA_NOT_FOUND and return,
         aContinuum does not contain any rows}
 */
/*----------------------------------------------------------------------------*/
void
muse_sky_qc_continuum(cpl_propertylist *aHeader, cpl_table *aContinuum,
                      const char *aPrefix)
{
  if (!aHeader || !aContinuum || !aPrefix) {
    cpl_error_set(__func__, CPL_ERROR_NULL_INPUT);
    return;
  }
  cpl_size irow, nrow = cpl_table_get_nrow(aContinuum);
  if (nrow < 1) {
    cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
    return;
  }

  double flux = 0.0;
  for (irow = 0; irow < nrow; irow++) {
    flux += cpl_table_get_double(aContinuum, "flux", irow, NULL);
  }
  char keyword[KEYWORD_LENGTH];
  snprintf(keyword, KEYWORD_LENGTH, "%s CONT FLUX", aPrefix);
  if (!isfinite(flux)) {
    /* again, workaround for weird CFITSIO error */
    cpl_propertylist_append_double(aHeader, keyword, -9999.999);
    cpl_msg_error(__func__, "Sky-continuum contains infinite values, fit may "
                  "have failed!");
  } else {
    cpl_propertylist_append_double(aHeader, keyword, flux);
  }
  double maxdev = 0.0,
         prev = cpl_table_get_double(aContinuum, "flux", 0, NULL),
         l_prev = cpl_table_get_double(aContinuum, "lambda", 0, NULL);
  for (irow = 1; irow < nrow; irow++) {
    double cur = cpl_table_get_double(aContinuum, "flux", irow, NULL),
           l_cur = cpl_table_get_double(aContinuum, "lambda", irow, NULL),
           dev = fabs((cur - prev)/ (l_cur - l_prev));
    if (maxdev < dev) {
      maxdev = dev;
    }
    prev = cur;
    l_prev = l_cur;
  } /* for irow (continuum table rows) */
  snprintf(keyword, KEYWORD_LENGTH, "%s CONT MAXDEV", aPrefix);
  cpl_propertylist_append_double(aHeader, keyword, maxdev);
} /* muse_sky_qc_continuum() */

/**@}*/
