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

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

/*----------------------------------------------------------------------------*
 *                             Includes                                       *
 *----------------------------------------------------------------------------*/
#include <cpl.h>
#include "muse_mask.h"

#include "muse_utils.h"

/*----------------------------------------------------------------------------*/
/**
 * @defgroup muse_mask         Mask handling
 *
 * This module contains a simple wrapper around the cpl_mask object, so that we
 * can easily pass a mask together with its (FITS) header around to between
 * functions.
 */
/*----------------------------------------------------------------------------*/
/**@{*/

/*----------------------------------------------------------------------------*/
/**
  @brief    Allocate memory for a new <tt><b>muse</b></tt> object.
  @return   a new <tt><b>muse_mask *</b></tt> or @c NULL on error
  @remark   The returned object has to be deallocated using
            <tt><b>muse_mask_delete()</b></tt>.
  @remark   This function does not allocate the contents of the elements,
            these have to be allocated with @c cpl_mask_new() or
            @c cpl_propertylist_new(), respectively, or equivalent functions.

  Simply allocate memory to store the pointers of the <tt><b>muse_mask</b></tt>
  structure.
 */
/*----------------------------------------------------------------------------*/
muse_mask *
muse_mask_new(void)
{
  return (muse_mask *)cpl_calloc(1, sizeof(muse_mask));
} /* muse_mask_new() */

/*----------------------------------------------------------------------------*/
/**
  @brief    Deallocate memory associated to a muse_mask object.
  @param    aMask   input MUSE mask

  Just calls @c cpl_mask_delete() and @c cpl_propertylist_delete() for the
  four components of a <tt><b>muse_mask</b></tt>, and frees memory for the
  aMask pointer. As a safeguard, it checks if a valid pointer was passed,
  so that crashes cannot occur.
 */
/*----------------------------------------------------------------------------*/
void
muse_mask_delete(muse_mask *aMask)
{
  if (!aMask) {
    return;
  }
  cpl_mask_delete(aMask->mask);
  cpl_propertylist_delete(aMask->header);
  cpl_free(aMask);
} /* muse_mask_delete() */

/*----------------------------------------------------------------------------*/
/**
  @brief    Load a mask file and its FITS header
  @param    aFilename      name of the file to load
  @return   a new <tt><b>muse_mask *</b></tt> or NULL on error
  @remark   The new mask has to be deallocated using
            <tt><b>muse_mask_delete()</b></tt>.
  @remark   Only FITS keywords from the primary FITS header will be loaded.

  @error{return NULL\, propagate CPL error code,
         cpl_propertylist_load() fails (this handles the case of an invalid or empty filename)}
  @error{return NULL\, propagate CPL error code, cpl_mask_load() fails}
 */
/*----------------------------------------------------------------------------*/
muse_mask *
muse_mask_load(const char *aFilename)
{
  muse_mask *mask = muse_mask_new();
  if (mask == NULL) {
    return NULL;
  }

  mask->header = cpl_propertylist_load(aFilename, 0);
  if (!mask->header) {
    cpl_msg_error(__func__, "Loading \"%s\" failed: %s", aFilename,
                  cpl_error_get_message());
    muse_mask_delete(mask);
    return NULL;
  }

  mask->mask = cpl_mask_load(aFilename, 0, 0);
  if (mask->mask == NULL) {
    cpl_msg_error(__func__, "Could not load mask from \"%s\": %s",
                  aFilename, cpl_error_get_message());
    muse_mask_delete(mask);
    return NULL;
  }

  return mask;
} /* muse_mask_load() */

/*----------------------------------------------------------------------------*/
/**
  @brief    Save the data and the FITS headers of a MUSE mask to a file.
  @param    aMask          input MUSE mask
  @param    aFilename      name of the output file
  @return   CPL_ERROR_NONE or the relevant cpl_error_code on error
  @remark   The primary headers of the output file will be constructed from
            the header member of the <tt><b>muse_mask</b></tt> structure.

  @error{return CPL_ERROR_NULL_INPUT, aImage or aFilename are NULL}
  @error{return CPL error code, failure to save any of the components}
 */
/*----------------------------------------------------------------------------*/
cpl_error_code
muse_mask_save(muse_mask *aMask, const char *aFilename)
{
  cpl_ensure_code(aMask && aFilename, CPL_ERROR_NULL_INPUT);

  cpl_image *image = cpl_image_new_from_mask(aMask->mask);
  cpl_error_code err = cpl_image_save(image, aFilename, CPL_TYPE_UNSPECIFIED,
                                      aMask->header, CPL_IO_CREATE);
  cpl_image_delete(image);

  if (err != CPL_ERROR_NONE) {
    cpl_msg_error(__func__, "Could not save mask %s: %s",
                  aFilename, cpl_error_get_message());
    return err;
  }

  return CPL_ERROR_NONE;
} /* muse_mask_save() */

/**@}*/
