/* -*- 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-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.
 */

#include <muse.h>
#include <string.h>

/*----------------------------------------------------------------------------*/
/**
 * @defgroup tools_musebpfromdq             Tool muse_badpix_from_dq
 *
 * <b>muse_badpix_from_dq</b>: Convert the DQ image extension to a BADPIX_TABLE.
 *
 * Create a BADPIX_TABLE file from the DQ image extension of a MUSE master
 * calibration file. It loads the DQ image extension, loops through all pixels
 * and adds all bad pixels into the table.
 * Optionally, it merges the image DQ information into an existing BADPIX_TABLE.
 *
 * <b>Command line arguments:</b>
 *   - <tt>-i INTABLE</tt> (optional)\n
 *     do not create a new BADPIX_TABLE but start from this one, i.e. either
 *     merge the table of the relevant IFU, or append a new one, if this IFU
 *     is not yet stored in the input file
 *   - <tt><b>INIMAGE</b></tt>\n
 *     the filename of the input image file to use; it needs to contain a
 *     data quality extension
 *   - <tt><b>OUTTABLE</b></tt>\n
 *     the filename of the output BADPIX_TABLE file to use
 *
 * <b>Return values:</b>
 *   - <tt> 0</tt>\n   Success
 *   - <tt> 1</tt>\n   less than two filenames given
 *   - <tt> 2</tt>\n   argument <tt>-i</tt> without filename
 *   - <tt> 9</tt>\n   unknown option given
 *   - <tt>10</tt>\n   input image could not be loaded from file
 */
/*----------------------------------------------------------------------------*/

/**@{*/

#define PRINT_USAGE(rc)                                                        \
  fprintf(stderr, "Usage: %s [ -i INTABLE ] INFILE OUTTABLE\n", argv[0]);      \
  cpl_end(); return (rc);

int main(int argc, char **argv)
{
  cpl_init(CPL_INIT_DEFAULT);
  muse_processing_recipeinfo(NULL);
  if (argc <= 2) {
    /* two filenames are needed at least */
    PRINT_USAGE(1);
  }

  if (getenv("ESOREX_MSG_LEVEL") && !strncmp(getenv("ESOREX_MSG_LEVEL"),
                                             "debug", 6)) {
    cpl_msg_set_level(CPL_MSG_DEBUG);
  }

  char *iname = NULL, /* input image */
       *tiname = NULL, /* optional input table */
       *toname = NULL; /* output table */

  /* argument processing */
  int i;
  for (i = 1; i < argc; i++) {
    if (strncmp(argv[i], "-i", 3) == 0) {
      /* skip to next arg to input table filename */
      i++;
      if (i < argc) {
        tiname = argv[i];
      } else {
        PRINT_USAGE(2);
      }
    } else if (strncmp(argv[i], "-", 1) == 0) { /* unallowed options */
      PRINT_USAGE(9);
    } else {
      if (iname && toname) {
        break; /* we have the possible names, skip the rest */
      }
      if (!iname) {
        iname = argv[i]; /* set the name for the input image */
      } else {
        toname = argv[i]; /* set the name for the output table */
      }
    }
  } /* for i (all arguments) */

  int extension = cpl_fits_find_extension(iname, EXTNAME_DQ);
  cpl_image *image = cpl_image_load(iname, CPL_TYPE_INT, 0, extension);
  if (!image) {
    PRINT_USAGE(10);
  }
  /* load main headers */
  cpl_propertylist *header = cpl_propertylist_load(iname, 0);
  int nx = cpl_image_get_size_x(image),
      ny = cpl_image_get_size_y(image);
  unsigned char nifu = muse_utils_get_ifu(header);
  printf("Read %dx%d image of IFU %hhu from \"%s\"\n", nx, ny, nifu, iname);

  /* part1: ======================================= *
   * convert the DQ from the image into a new table */
  cpl_table *table = muse_quality_convert_dq(image);
#if 0
  cpl_table_dump(table, 0, 1000, stdout);
  fflush(stdout);
#endif
  cpl_size nrow = cpl_table_get_nrow(table);
  printf("%"CPL_SIZE_FORMAT" bad pixel%s found\n", nrow, nrow != 1 ? "s" : "");

  /* part2: ============================================ *
   * load and handle the input badpix table if it exists */
  if (tiname) { /* try to open the input table, verify that it really exists */
    cpl_propertylist *htest = cpl_propertylist_load(tiname, 0);
    if (htest) {
      cpl_propertylist_delete(htest);
    } else {
      printf("WARNING: could not open input table \"%s\"!\n", tiname);
      tiname = NULL; /* it doesn't exist, don't keep the name */
    } /* else */
  } /* if tiname */

  /* merge created table with existing one, if there is one */
  cpl_table *intable = NULL;
  int inext = -1;
  if (tiname) {
    char *extifu = cpl_sprintf("CHAN%02hhu", nifu);
    intable = muse_quality_merge_badpix_from_file(table, tiname, extifu, &inext);
    cpl_free(extifu);
    if (!intable) {
      intable = table;
    } /* if !intable */
  } /* if tiname */
  /* copy the input BADPIX_TABLE, replacing the one extension we modified */
  muse_quality_copy_badpix_table(tiname, toname, inext, intable);

  /* save or append the extension if not already done above */
  if (inext < 0) {
    cpl_propertylist *pheader = NULL;
    /* create a primary header, if we create a new file */
    if (!tiname) {
      pheader = cpl_propertylist_load_regexp(iname, 0, "TELESCOP|INSTRUME|"
                                             "ESO DET ", 0);
      /* remove exposure-specifc info and the stuff about     *
       * CHIP and OUTi again, that belongs into the extension */
      cpl_propertylist_erase_regexp(pheader, "ESO DET DEV[0-9] (SHUT |EXP )|"
                                    "ESO DET (EXP |[DU]IT|NDIT|DKTM)", 0);
      cpl_propertylist_erase_regexp(pheader, "ESO DET (CHIP |OUT[1-4])", 0);
      cpl_propertylist_update_string(pheader, "OBJECT",
                                     "Bad pixel table for MUSE (BADPIX_TABLE)");
      cpl_propertylist_update_string(pheader, "PIPEFILE", toname);
      cpl_propertylist_set_comment(pheader, "PIPEFILE",
                                   "pretend to be a pipeline output file");
    } /* if !tiname */
    /* for saving, cut the extension header to the necessary *
     * information of extension name and about CHIP and OUTi */
    cpl_propertylist_erase_regexp(header, "^EXT|ESO DET (CHIP |OUT[1-4])", 1);
    /* create new file if necessary or append to the file saved above */
    cpl_error_code rc = cpl_table_save(table, pheader, header, toname,
                                       pheader ? CPL_IO_CREATE : CPL_IO_EXTEND);
    if (rc != CPL_ERROR_NONE) {
      fprintf(stderr, "Saving to \"%s\" failed (rc=%d): %s\n", toname, rc,
              cpl_error_get_message());
    } else {
      printf("Saved to \"%s\"\n", toname);
    }
    cpl_propertylist_delete(pheader); /* in case it was created */
  } /* if inext < 0  (not saved yet) */
  cpl_table_delete(table);
  cpl_image_delete(image);
  cpl_propertylist_delete(header);

  if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
    printf("Output file \"%s\" has primary header and %"CPL_SIZE_FORMAT
           " extensions\n", toname, cpl_fits_count_extensions(toname));
    cpl_errorstate_dump(0, CPL_FALSE, NULL);
    cpl_memory_dump();
  }
  cpl_end();
  return 0;
}

/**@}*/
