/** @file  tst_psMetadata_01.c
*
*  @brief Test driver for psMetadata functions
*
*  This test driver contains the following tests for psMetadata:
*     Test A - Read 1st hdr from simple FITS file
*     Test B - Read 2nd hdr from complex FITS file
*     Test C - Read named hdr from complex FITS file
*     Test D - Remove items with same name from all metadata
*     Test E - Attempt to use null file descriptor
*     Test F - Attempt to open nonexistant file
*     Test G - Attempt to use two null inputs
*     Test H - Attempt to use bad extNum
*     Test I - Attempt to use bad extNameTest
*     Test J - Read named hdr w/ invalid extnum
*     Test K - Free psMetadata
*
*  @author  Ross Harman, MHPCC
*
*  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
*  @date  $Date: 2005-07-21 02:39:57 $
*
*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
*
*/

#include <string.h>
#include "pslib_strict.h"
#include "psTest.h"

static void printMetadataItem(psMetadataItem *metadataItem, char *spaces);
static void printMetadata(psMetadata *metadata);
static void printMetadataList(psList *metadataItemList, char* spaces);
static void printMetadataTable(psHash *mdTable);

static void printMetadata(psMetadata *metadata)
{
    printf("Contents of metadata list:\n");
    printMetadataList(metadata->list, " ");
    printf("\nContents of metadata table:\n");
    printMetadataTable(metadata->hash);
}

static void printMetadataList(psList *metadataItemList, char* spaces)
{
    psMetadataItem *entryChild = NULL;

    psListIterator* iter = psListIteratorAlloc(metadataItemList, PS_LIST_HEAD, true);

    while ( (entryChild=psListGetAndIncrement(iter)) != NULL) {
        printMetadataItem(entryChild, spaces);
    }

    psFree(iter);

}

static void printMetadataTable(psHash *mdTable)
{
    psS32 i;
    psHashBucket* ptr = NULL;
    for(i=0; i<mdTable->n; i++) {
        ptr = mdTable->buckets[i];
        while (ptr != NULL) {
            printMetadataItem(ptr->data, " ");
            ptr = ptr->next;
        }
    }
}

static void printMetadataItem(psMetadataItem *metadataItem, char *spaces)
{
    printf("%sKey Name: %8s  ", spaces, metadataItem->name);
    printf("Key mdType: 0x%08x  ", metadataItem->type);

    switch (metadataItem->type) {
    case PS_META_MULTI:
        printf("Key Value: %17c", ' ');
        break;
    case PS_META_BOOL:
        printf("Key Value: %15d  ", metadataItem->data.B);
        break;
    case PS_META_S32:
        printf("Key Value: %15d  ", metadataItem->data.S32);
        break;
    case PS_META_F32:
        printf("Key Value: %15.3f  ", metadataItem->data.F32);
        break;
    case PS_META_F64:
        printf("Key Value: %15.3f  ", metadataItem->data.F64);
        break;
    case PS_META_STR:
        printf("Key Value: %15s  ", (char*)metadataItem->data.V);
        break;
    default:
        printf("Bad type: %d ", metadataItem->type);
    }
    printf("Key Comment: %s\n", metadataItem->comment);

    if(metadataItem->data.V && metadataItem->type==PS_META_MULTI) {
        printMetadataList(metadataItem->data.V, "    ");
    }
}


psS32 main(psS32 argc, char* argv[])
{
    psMetadata *metadata1 = NULL;
    psMetadata *metadata2 = NULL;
    psMetadata *metadata3 = NULL;


    // Test A - Read 1st hdr from simple FITS file

    /* Header contents for header_1.fits:

        SIMPLE  =                    T / file does conform to FITS standard
        BITPIX  =                    8 / number of bits per data pixel
        NAXIS   =                    0 / number of data axes
        HISTORY File modified by user 'harman' with fv  on 2004-08-04T11:11:18
        END
    */
    printPositiveTestHeader(stdout, "psMetadata", "Test A - Read 1st hdr from simple FITS file");
    metadata1 = psMetadataReadHeader(metadata1, NULL, 1, "header_1.fits");
    printMetadata(metadata1);
    printFooter(stdout, "psMetadata", "Test A - Read 1st hdr from simple FITS file", true);

    // Test B - Read 2nd hdr from complex FITS file

    /* Header contents for header_2.fits:

        SIMPLE  =                    T / file does conform to FITS standard
        BITPIX  =                  -64 / number of bits per data pixel
        NAXIS   =                    1 / number of data axes
        NAXIS1  =                   64 / length of data axis 1
        EXTEND  =                    T / FITS dataset may contain extensions
        COMMENT   FITS (Flexible Image Transport System) format is defined in 'Astronomy
        COMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H
        END
        <DATA>

        XTENSION= 'IMAGE   '           / IMAGE extension
        BITPIX  =                  -64 / number of bits per data pixel
        NAXIS   =                    1 / number of data axes
        NAXIS1  =                   64 / length of data axis 1
        PCOUNT  =                    0 / required keyword; must = 0
        GCOUNT  =                    1 / required keyword; must = 1
        BITPIX  =                  -64 / number of bits per data pixel
        EXTNAME = 'MY_DATA_1'
        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:14:45
        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:15:29
        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:21:18
        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:21:46
        END
        <DATA>

        XTENSION= 'IMAGE   '           / IMAGE extension
        BITPIX  =                  -64 / number of bits per data pixel
        NAXIS   =                    1 / number of data axes
        NAXIS1  =                   64 / length of data axis 1
        PCOUNT  =                    0 / required keyword; must = 0
        GCOUNT  =                    1 / required keyword; must = 1
        EXTNAME = 'MY_DATA_2'
        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:22:12
        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:22:52
        END
        <DATA>
    */
    printPositiveTestHeader(stdout, "psMetadata", "Test B - Read 2nd hdr from complex FITS file");
    metadata2 = psMetadataReadHeader(metadata2, NULL, 2, "header_2.fits");
    printMetadata(metadata2);
    printFooter(stdout, "psMetadata", "Test B - Read 2nd hdr from complex FITS file", true);

    // Test C - Read named hdr from complex FITS file
    printPositiveTestHeader(stdout, "psMetadata", "Test C - Read named hdr from complex FITS file");
    metadata3 = psMetadataReadHeader(metadata3, "MY_DATA_2", -1, "header_2.fits");
    printMetadata(metadata3);
    printFooter(stdout, "psMetadata", "Test C - Read named hdr from complex FITS file", true);


    // Test D - Remove items with same name from all metadata
    printPositiveTestHeader(stdout, "psMetadata", "Test D - Remove items with same name from all metadata");
    printf("Removed HISTORY from all metadata from prior test. Resulting metadata:\n\n");
    psMetadataRemove(metadata3, 0, "HISTORY");
    printMetadata(metadata3);
    printFooter(stdout, "psMetadata", "Test D - Remove items with same name from all metadata", true);


    // Test E - Attempt to use null file filename
    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to use null filename",
                            "Null fileName not allowed", 0);
    psMetadataReadHeader(NULL, NULL, 1, NULL);
    printFooter(stdout, "psMetadata", "Test E - Attempt to use null filename", true);


    // Test F - Attempt to open nonexistant file
    printNegativeTestHeader(stdout,"psMetadata", "Test F - Attempt to open nonexistant file",
                            "FITS error while opening file: missing.dat...Couldn't close FITS file...", 0);
    psMetadataReadHeader(NULL, NULL, 1, "missing.dat");
    printFooter(stdout, "psMetadata", "Test F - Attempt to open nonexistant file", true);


    // Test G - Attempt to use two null inputs
    printNegativeTestHeader(stdout,"psMetadata", "Test G - Attempt to use two null inputs",
                            "Null extName and extNum = 0 not allowed", 0);
    psMetadataReadHeader(NULL, NULL, 0, "header_2.fits");
    printFooter(stdout, "psMetadata", "Test G - Attempt to use two null inputs", true);


    // Test H - Attempt to use bad extNum
    printNegativeTestHeader(stdout,"psMetadata", "Test H - Attempt to use bad extNum",
                            "FITS error while locating header 22: tried to move past end of file", 0);
    metadata1 = psMetadataReadHeader(metadata1, NULL, 22, "header_2.fits");
    if (metadata1 != NULL ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataReadHeader did not return null when invalid ext given.");
        return 10;
    }
    printFooter(stdout, "psMetadata", "Test H - Attempt to use bad extNum", true);


    // Test I - Attempt to use bad extName
    printNegativeTestHeader(stdout,"psMetadata", "Test I - Attempt to use bad extName",
                            "FITS error while locating header AARGH: illegal HDU number", 0);
    metadata1 = psMetadataReadHeader(NULL, "AARGH", -1, "header_2.fits");
    if (metadata1 != NULL ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataReadHeader did not return null invalid extname give.");
        return 11;
    }
    printFooter(stdout, "psMetadata", "Test I - Attempt to use bad extName", true);


    // Test J - Read named hdr w/ invalid extnum
    printNegativeTestHeader(stdout, "psMetadata", "Test J - Read named hdr w/ invalid extnum",
                            "If extName specified, extNum should be -1.", 0);
    metadata1 = psMetadataReadHeader(NULL, NULL, 0, "header_2.fits");
    if (metadata1 != NULL ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataReadHeader did not return null w/ valid extname, invalid extnum");
        return 12;
    }
    printFooter(stdout, "psMetadata", "Test J - Read named hdr w/ invalid extnum", true);


    // Test K - Free psMetadata
    printPositiveTestHeader(stdout, "psMetadata", "Test K - Free psMetadata");
    psFree(metadata1);
    psFree(metadata2);
    psFree(metadata3);
    if(psMemCheckLeaks(0, NULL, stdout,false)) {
        psError(PS_ERR_UNKNOWN,true,"Memory leaks detected.");
    }
    psMemCheckCorruption(0);
    psS32 nBad = psMemCheckCorruption(0);
    if(nBad) {
        printf("ERROR: Found %d bad memory blocks\n", nBad);
    }
    printFooter(stdout, "psMetadata", "Test K - Free psMetadata", true);

    return 0;
}
