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

#define _DEFAULT_SOURCE
#define _BSD_SOURCE /* get mkdtemp() from stdlib.h */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

#include <muse.h>

#define DIR_TEMPLATE "/tmp/muse_mask_test_XXXXXX"
#define OBJECT_STRING "Test muse_mask"

/*----------------------------------------------------------------------------*/
/**
  @brief    test program to check that all the functions working on muse_masks
            work correctly
 */
/*----------------------------------------------------------------------------*/
int main(int argc, char **argv)
{
  UNUSED_ARGUMENTS(argc, argv);
  cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_DEBUG);

  /* create a muse_mask */
  muse_mask *mask = muse_mask_new();
  /* now the muse_mask should be non-NULL and the components should be NULL */
  cpl_test_nonnull(mask);
  cpl_test(mask->mask == NULL);
  cpl_test_null(mask->header);

  /* test freeing when the muse_mask doesn't actually contain an mask */
  cpl_errorstate state = cpl_errorstate_get();
  muse_mask_delete(mask);
  mask = NULL;
  cpl_test(cpl_errorstate_is_equal(state));


  /* now create a muse_mask with content */
  int nx = 10, ny = 5;
  mask = muse_mask_new();
  /* add noice in the data extension */
  mask->mask = cpl_mask_new(nx, ny);
  cpl_test_nonnull(mask->mask);

  /* add the headers, and set at least the OBJECT header */
  mask->header = cpl_propertylist_new();
  cpl_test_nonnull(mask->header);
  cpl_propertylist_append_string(mask->header, "OBJECT", OBJECT_STRING);

  /* save the mask to a (temporary) file */
  char dirtemplate[FILENAME_MAX] = DIR_TEMPLATE;
  char *dir = mkdtemp(dirtemplate);
  char *file = cpl_sprintf("%s/%s", dir, "muse_mask.fits");
  cpl_error_code err = muse_mask_save(mask, (const char *)file);
  cpl_test_zero(err);
  cpl_msg_info(__func__, "Written to \"%s\"", file);
  struct stat sb;
  cpl_test_zero(stat(file, &sb));
  /* the file written should be a normal file with size greater than zero... */
  cpl_test(S_ISREG(sb.st_mode) && sb.st_size > 0);
  /* ... and contain no extensions */
  cpl_test(cpl_fits_count_extensions(file) == 0);

  /* try to load the file again that we just saved */
  muse_mask *maskl = muse_mask_load(file);
  cpl_test_nonnull(maskl);
  cpl_test_nonnull(maskl->header);
  const char *object = cpl_propertylist_get_string(maskl->header, "OBJECT");
  cpl_test_zero(strncmp(object, OBJECT_STRING, strlen(OBJECT_STRING) + 1));

  /* Test that the masks are identical */
  cpl_mask_xor(mask->mask, maskl->mask);
  cpl_test_eq(cpl_mask_count(mask->mask), 0);

  /* test freeing when the muse_mask is filled */
  state = cpl_errorstate_get();
  muse_mask_delete(maskl);
  cpl_test(cpl_errorstate_is_equal(state));

  /* try to load from non-existing file */
  state = cpl_errorstate_get();
  muse_mask *mask_test = muse_mask_load("blabla");
  cpl_test(mask_test == NULL && !cpl_errorstate_is_equal(state));
  cpl_errorstate_set(state);

  /* now we can remove the file again, use the return values to check that *
   * nothing else went wrong with the file in the meantime                 */
  cpl_test_zero(remove(file));
  cpl_test_zero(rmdir(dir));
  cpl_free(file);
  muse_mask_delete(mask);

  return cpl_test_end(0);
}
