/** @file  psFits.h
 *
 *  @brief Contains Fits I/O routines
 *
 *  @ingroup FileIO
 *
 *  @author Robert DeSonia, MHPCC
 *
 *  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2006-07-08 03:06:40 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 */

#ifndef PS_FITS_H
#define PS_FITS_H

#include <fitsio.h>

#include "psType.h"
#include "psArray.h"
#include "psVector.h"
#include "psMetadata.h"
#include "psImage.h"

/// @addtogroup FileIO
/// @{

/** FITS HDU type.
 *
 *  Enumeration for FITS HDU type.
 *
 */
typedef enum {
    PS_FITS_TYPE_NONE = -1,            ///< Unknown HDU type
    PS_FITS_TYPE_IMAGE = IMAGE_HDU,    ///< Image HDU type
    PS_FITS_TYPE_BINARY_TABLE = BINARY_TBL, ///< Binary table HDU type
    PS_FITS_TYPE_ASCII_TABLE = ASCII_TBL,   ///< ASCII table HDU type
    PS_FITS_TYPE_ANY = ANY_HDU         ///< Any HDU type
} psFitsType;

/** FITS file object.
 *
 *  This object should be considered opaque to the user; no item in this
 *  struct should be accessed directly.
 *
 */
typedef struct
{
    fitsfile* fd;                      ///< the CFITSIO fits files handle.
    bool writable;                     ///< Is the file writable?
}
psFits;

/** Opens a FITS file and allocates the associated psFits object.
 *
 *  @return psFits*    new psFits object for the FITS files specified or
 *                     NULL if the open of the FITS file failed
 */
psFits* psFitsOpen(
    const char* filename,              ///< the FITS file name
    const char* mode
    /**< File open mode. Could be one of the following:
     *       'r' (read only),
     *       'r+' (read & write),
     *       'rw' (same as 'r+'), or
     *       'w' (create new file for writing)
     */
);

/** Closes a FITS file.
 *
 *  @return bool      TRUE if FITS file was successfully closed, otherwise FALSE
 */
bool psFitsClose(
    psFits* fits                       ///< psFits object to close
);

/** Checks the type of a particular pointer.
 *
 *  Uses the appropriate deallocation function in psMemBlock to check the ptr
 *  datatype.
 *
 *  @return bool:       True if the pointer matches a psFits structure, false
 *                      otherwise.
 */
bool psMemCheckFits(
    psPtr ptr                          ///< the pointer whose type to check
);


/** Moves the FITS HDU to the specified extension name.
 *
 *  @return bool        TRUE if the extension name was found and move was
 *                      successful, otherwise FALSE
 */
bool psFitsMoveExtName(
    const psFits* fits,                ///< the psFits object to move
    const char* extname                ///< the extension name
);

/** Moves the FITS HDU to the specified extension number
 *
 *  @return bool        TRUE if the extension number was found and move was
 *                      successful, otherwise FALSE
 */
bool psFitsMoveExtNum(
    const psFits* fits,                ///< the psFits object to move
    int extnum,                        ///< the extension number to move to (zero is primary HDU)
    bool relative                      ///< if true, extnum is a relative number to the current position
);

/** Moves the FITS HDU to the end of the file
 *
 *  @return bool        TRUE if the move was successful, otherwise FALSE
*/
bool psFitsMoveLast(
    psFits* fits                       ///< the psFits object to move
);

/** Get the current extension number, where 0 is the primary HDU.
 *
 *  @return int        Current HDU number of the psFits file or < 0 if an error
 *                     occurred.
 */
int psFitsGetExtNum(
    const psFits* fits                 ///< the psFits object
);

/** Get the current extension name.
 *
 *  @return int        Current HDU name of the psFits file or NULL if an
 *                     error occurred.
 */
psString psFitsGetExtName(
    const psFits* fits                 ///< the psFits object
);

/** Set the current extension's name
 *
 *  @return bool       TRUE if the extension was successfully set, otherwise FALSE.
 */
bool psFitsSetExtName(
    psFits* fits,                      ///< the psFits object
    const char* name                   ///< the extension name
);

/** Get the total number of HDUs in the FITS file.
 *
 *  @return int        The total number of HDUs in the FITS file or < 0 if an
 *                     error occurred.
 */
int psFitsGetSize(
    const psFits* fits                 ///< the psFits object
);

/** Remove the an HDU as specified by number
 *
 *  @return bool        TRUE if the specified HDU was removed, otherwise FALSE
 */
bool psFitsDeleteExtNum(
    psFits* fits,                      ///< the psFits object
    int extnum,                        ///< the extension number to delete (zero is primary HDU)
    bool relative                      ///< if true, extnum is a relative number to the current position
);

/** Remove the an HDU as specified by extension name
 *
 *  @return bool        TRUE if the specified HDU was removed, otherwise FALSE
 */
bool psFitsDeleteExtName(
    psFits* fits,                      ///< the psFits object
    const char* extname                ///< the extension name to delete
);

/** Get the extension type of the current HDU.
 *
 *  @return psFitsType The type of the current HDU.  If PS_FITS_TYPE_UNKNOWN,
 *                     the type could not be determined.
 */
psFitsType psFitsGetExtType(
    const psFits* fits                 ///< the psFits object
);

/** Delete all extensions after the current position
 *
 *  @return bool        TRUE if the operation was successful, otherwise FALSE
 */
bool psFitsTruncate(
    psFits* fits                       ///< the psFits object
);

// Return the psLib type, given a cfitsio data type
psDataType p_psFitsTypeFromCfitsio(int datatype // cfitsio data type
                                  );

// Return the cfitsio data type, given a psLib type
bool p_psFitsTypeToCfitsio(psDataType type, // psLib data type
                           int* bitPix, // The corresponding BITPIX (returned)
                           double* bZero, // The corresponding BZERO (returned)
                           int* dataType// The corresponding cfitsio data type (returned)
                          );

/// @}

#endif // #ifndef PS_FITS_H
