/* -*- 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) 2007-2015 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.
 */

#include <muse.h>

/*----------------------------------------------------------------------------*/
/**
  @brief    Short test program to check that row-by-row sky subtraction works.
            This tests the functions
               muse_sky_subtract_rowbyrow_mask()
               muse_sky_subtract_rowbyrow()
 */
/*----------------------------------------------------------------------------*/
int main(int argc, char **argv)
{
  cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_DEBUG);

  muse_image *image = NULL;
  cpl_table *tracetable = NULL;
  if (argc == 3) {
    /* assume that the file passed on the command line is an input image */
    cpl_msg_info(__func__, "command line arguments detected, will try to load %s/%s",
                 argv[1], argv[2]);
    image = muse_image_load(argv[1]);
    tracetable = cpl_table_load(argv[2], 1, 1);
  } else {
    image = muse_image_load(BASEFILENAME"_in.fits");
    tracetable = cpl_table_load(BASEFILENAME"_trace.fits", 1, 1);
  }
  cpl_error_reset();
  if (!image || !image->data || !image->stat) {
    cpl_msg_error(__func__, "Could not load test image: %s", cpl_error_get_message());
    muse_image_delete(image);
    return cpl_test_end(2);
  }
  if (!tracetable) {
    cpl_msg_error(__func__, "Could not load trace table: %s", cpl_error_get_message());
    return cpl_test_end(3);
  }
  /* duplicate it for the 2nd test */
  muse_image *image2 = muse_image_duplicate(image);

  /* it should (continue to) work with a normal trace table */
  cpl_error_code rc = muse_sky_subtract_rowbyrow_mask(image, tracetable);
  cpl_test(rc == CPL_ERROR_NONE);
  rc = muse_sky_subtract_rowbyrow(image, tracetable, 3., 4);
  cpl_test(rc == CPL_ERROR_NONE);
  /* the result should be somewhere around zero */
  cpl_test(fabs(cpl_image_get_mean(image->data)) < 3.);
  cpl_test(fabs(cpl_image_get_median(image->data)) < 1.);
#if 0
  muse_image_save(image, "sky_rowbyrow_subtracted_with_tracetable.fits");
#endif
  muse_image_delete(image);

  /* fail, if the input image is missing */
  cpl_errorstate state = cpl_errorstate_get();
  cpl_test(muse_sky_subtract_rowbyrow_mask(NULL, tracetable) == CPL_ERROR_NULL_INPUT);
  cpl_test(muse_sky_subtract_rowbyrow(NULL, tracetable, 3., 4) == CPL_ERROR_NULL_INPUT);
  cpl_errorstate_set(state);

  /* fail, if neither trace table nor slice center keywords are there */
  state = cpl_errorstate_get();
  cpl_test(muse_sky_subtract_rowbyrow_mask(image2, NULL) == CPL_ERROR_ILLEGAL_INPUT);
  cpl_test(muse_sky_subtract_rowbyrow(image2, NULL, 3., 4) == CPL_ERROR_ILLEGAL_INPUT);
  cpl_errorstate_set(state);

  /* but it should also work with slice center keywords, so set them up */
  int nx = cpl_image_get_size_x(image2->data),
      ny = cpl_image_get_size_y(image2->data);
  unsigned short nslice;
  for (nslice = 1; nslice <= kMuseSlicesPerCCD; nslice++) {
    cpl_polynomial **ptrace = muse_trace_table_get_polys_for_slice(tracetable,
                                                                   nslice);
    float middle = cpl_polynomial_eval_1d(ptrace[MUSE_TRACE_CENTER], ny/2, NULL);
    char *keyword = cpl_sprintf("ESO DRS MUSE SLICE%hu CENTER", nslice);
    cpl_propertylist_update_float(image2->header, keyword, middle);
    cpl_free(keyword);
    /* move along slice, and flag the pixel just outside it to EURO3D_MISSDATA */
    int *dq = cpl_image_get_data_int(image2->dq);
    int j;
    for (j = 0; j < ny; j++) {
      int l = floor(cpl_polynomial_eval_1d(ptrace[MUSE_TRACE_LEFT], j+1, NULL)),
          r = ceil(cpl_polynomial_eval_1d(ptrace[MUSE_TRACE_RIGHT], j+1, NULL));
      dq[(l-1) + j*nx] |= EURO3D_MISSDATA;
      dq[(r-1) + j*nx] |= EURO3D_MISSDATA;
    } /* for j (vertical image pixels) */
    muse_trace_polys_delete(ptrace);
  } /* for nslice */
  cpl_table_delete(tracetable);
  rc = muse_sky_subtract_rowbyrow_mask(image2, NULL);
  cpl_test(rc == CPL_ERROR_NONE);
  rc = muse_sky_subtract_rowbyrow(image2, NULL, 3., 4);
  cpl_test(rc == CPL_ERROR_NONE);
  /* the result should be somewhere around zero */
  cpl_test(fabs(cpl_image_get_mean(image2->data)) < 3.);
  cpl_test(fabs(cpl_image_get_median(image2->data)) < 1.);
#if 0
  muse_image_save(image2, "sky_rowbyrow_subtracted_with_headers.fits");
#endif
  muse_image_delete(image2);

  return cpl_test_end(0);
}
