/* -*- 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) 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 <string.h>
#include <muse.h>

/*----------------------------------------------------------------------------*/
/**
 * @defgroup tools_museproductsmerge        Tool muse_products_merge
 *
 * <b>muse_products_merge</b>: Merge separate IFU-base products into one file.
 *
 * The input filenames can be of multiple product categories, pixel tables
 * will be ignored.
 *
 * <b>Command line arguments:</b>
 *   - <tt>-s</tt> (optional)\n
 *     sign the merged output product(s)
 *   - <tt>-d</tt> (optional)\n
 *     delete the input files after merging
 *   - <tt><b>FILENAMES</b></tt>\n
 *     the filenames of the separate input MUSE pipeline products
 *
 * <b>Return values:</b>
 *   - <tt> 0</tt>\n   Success
 *   - <tt> 1</tt>\n   not enough filename(s)
 *   - <tt> 9</tt>\n   unknown option given
 *   - <tt>10</tt>\n   no file(s) found that can be merged
 *   - <tt>50</tt>\n   unknown error
 */
/*----------------------------------------------------------------------------*/

/**@{*/

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

int main(int argc, char **argv)
{
  cpl_init(CPL_INIT_DEFAULT);
  muse_processing_recipeinfo(NULL);

  if (argc <= 3) {
    /* filename and two input files are needed at least */
    PRINT_USAGE(1);
  }

  /* argument processing */
  cpl_boolean dodelete = CPL_FALSE, /* do not delete inputs by default */
              dosign = CPL_FALSE; /* do not sign by default */
  cpl_array *inames = cpl_array_new(0, CPL_TYPE_STRING); /* input filenames */
  int nin = cpl_array_get_size(inames); /* number of input filenames */
  int i;
  for (i = 1; i < argc; i++) {
    if (strncmp(argv[i], "-s", 3) == 0) {
      dosign = CPL_TRUE;
    } else if (strncmp(argv[i], "-d", 3) == 0) {
      dodelete = CPL_TRUE;
    } else if (strncmp(argv[i], "-", 1) == 0) { /* unallowed options */
      PRINT_USAGE(9);
    } else {
      cpl_array_set_size(inames, ++nin); /* space for the new name */
      cpl_array_set_string(inames, nin - 1, argv[i]);
    }
  } /* for i (all arguments) */

  cpl_errorstate state = cpl_errorstate_get();

  /* create frameset from the list of input names */
  printf("Separate input product%s:\n", nin == 0 ? "" : "s");
  cpl_frameset *fset = cpl_frameset_new();
  for (i = 0; i < nin; i++) {
    cpl_frame *frame = cpl_frame_new();
    const char *fn = cpl_array_get_string(inames, i);
    cpl_frame_set_filename(frame, fn);

    cpl_propertylist *header = cpl_propertylist_load(fn, 0);
    const char *tag = muse_pfits_get_pro_catg(header);
    /* check input files for PRO.CATG and ensure that they are not pixel tables */
    if (tag && !strncmp(tag, "PIXTABLE_", 9)) {
      fprintf(stderr, "\tWARNING: \"%s\" (PRO.CATG %s), cannot merge this type!\n", fn, tag);
      cpl_frame_delete(frame);
      cpl_propertylist_delete(header);
      continue;
    }
    cpl_frame_set_tag(frame, tag);
    cpl_frame_set_group(frame, CPL_FRAME_GROUP_NONE);
    /* these frame properties have no consequences here */
    cpl_frame_set_type(frame, CPL_FRAME_TYPE_NONE);
    cpl_frame_set_level(frame, CPL_FRAME_LEVEL_NONE);
    printf("\t\"%s\" (PRO.CATG %s).\n", fn, tag);
    cpl_propertylist_delete(header);
#if 0
    printf("frame!\n");
    cpl_frame_dump(frame, stdout);
    fflush(stdout);
#endif
    cpl_frameset_insert(fset, frame);
  } /* for i (all input filenames) */
  cpl_array_delete(inames);

  /* check that there is something to be merged */
  nin = cpl_frameset_get_size(fset);
  if (nin <= 1) {
    cpl_frameset_delete(fset);
    PRINT_USAGE(10);
  }

  printf("Merging %d products, %s the input files...\n", nin,
         dodelete ? "deleting" : "keeping");
  muse_utils_frameset_merge_frames(fset, dodelete);
#if 0
  printf("merged frameset:\n");
  cpl_frameset_dump(fset, stdout);
  fflush(stdout);
#endif

  int nout = cpl_frameset_get_size(fset),
      nmerged = nout - (dodelete ? 0 : nin); /* subtract input files */
  if (dosign) {
    printf("Signing %d output product%s...\n", nmerged, nmerged == 0 ? "" : "s");
    cpl_dfs_sign_products(fset, CPL_DFS_SIGNATURE_DATAMD5 | CPL_DFS_SIGNATURE_CHECKSUM);
  }

  printf("Merged output product%s:\n", nout == 0 ? "" : "s");
  for (i = 0; i < nout; i++) {
    const cpl_frame *frame = cpl_frameset_get_position_const(fset, i);
    if (cpl_frame_get_group(frame) != CPL_FRAME_GROUP_PRODUCT) {
      continue; /* ignore (input) file */
    }
    const char *fn = cpl_frame_get_filename(frame);
    cpl_propertylist *header = cpl_propertylist_load(fn, 0);
    const char *tag = muse_pfits_get_pro_catg(header);
    int next = cpl_fits_count_extensions(fn);
    printf("\t\"%s\" (PRO.CATG %s, %d FITS extensions)\n", fn, tag, next);
    cpl_propertylist_delete(header);
  } /* for i (all output frames) */
  cpl_frameset_delete(fset);

  int rc = 0;
  if (!cpl_errorstate_is_equal(state)) {
    cpl_errorstate_dump(state, CPL_FALSE, muse_cplerrorstate_dump_some);
    rc = 50;
  }
  cpl_memory_dump(); /* only active when CPL_MEMORY_MODE != 0 */
  cpl_end();
  return rc;
}

/**@}*/
