#include <stdio.h>
#include <string.h>
#include "pslib.h"
#include "papmodule.h"


psMetadata *psMetadataLookupMD(bool *status, const psMetadata *md, const char *key)
{
    psMetadataItem *item = psMetadataLookup((psMetadata*)md, key); // The metadata with instruments
    psMetadata *value = NULL;		// The value to return
    if (!item) {
	// The given key isn't in the metadata
	if (status) {
	    *status = false;
	} else {
	    psError(PS_ERR_IO, true, "Couldn't find %s in the metadata.\n");
	}
    } else if (item->type != PS_META_META) {
	// The value at the key isn't metadata
	if (status) {
	    *status = false;
	} else {
	    psLogMsg(__func__, PS_LOG_WARN, "%s isn't of type PS_META_META, as expected.\n");
	}
	value = NULL;
    } else {
	// We have the requested metadata
	if (status) {
	    *status = true;
	}
	value = item->data.md; // The requested metadata
    }
    return value;
}


char *psMetadataLookupString(bool *status, const psMetadata *md, const char *key)
{
    psMetadataItem *item = psMetadataLookup((psMetadata*)md, key); // The metadata with instruments
    char *value = NULL;			// The value to return
    if (!item) {
	// The given key isn't in the metadata
	if (status) {
	    *status = false;
	} else {
	    psError(PS_ERR_IO, true, "Couldn't find %s in the metadata.\n");
	}
    } else if (item->type != PS_META_STR) {
	// The value at the key isn't of the desired type
	if (status) {
	    *status = false;
	} else {
	    psLogMsg(__func__, PS_LOG_WARN, "%s isn't of type PS_META_STR, as expected.\n");
	}
	value = NULL;
    } else {
	// We have the requested metadata
	if (status) {
	    *status = true;
	}
	value = item->data.V; // The requested metadata
    }
    return value;
}

papChip *psMetadataLookupChip(bool *status, const psMetadata *md, const char *key)
{
    psMetadataItem *item = psMetadataLookup((psMetadata*)md, key); // The metadata with instruments
    papChip *value = NULL;		// The value to return
    if (!item) {
	// The given key isn't in the metadata
	if (status) {
	    *status = false;
	} else {
	    psError(PS_ERR_IO, true, "Couldn't find %s in the metadata.\n");
	}
    } else if (item->type != PS_META_CHIP) {
	// The value at the key isn't of the desired type
	if (status) {
	    *status = false;
	} else {
	    psLogMsg(__func__, PS_LOG_WARN, "%s isn't of type PS_META_CHIP, as expected.\n");
	}
	value = NULL;
    } else {
	// We have the requested metadata
	if (status) {
	    *status = true;
	}
	value = item->data.V; // The requested metadata
    }
    return value;
}

papCell *psMetadataLookupCell(bool *status, const psMetadata *md, const char *key)
{
    psMetadataItem *item = psMetadataLookup((psMetadata*)md, key); // The metadata with instruments
    papCell *value = NULL;		// The value to return
    if (!item) {
	// The given key isn't in the metadata
	if (status) {
	    *status = false;
	} else {
	    psError(PS_ERR_IO, true, "Couldn't find %s in the metadata.\n");
	}
    } else if (item->type != PS_META_CELL) {
	// The value at the key isn't of the desired type
	if (status) {
	    *status = false;
	} else {
	    psLogMsg(__func__, PS_LOG_WARN, "%s isn't of type PS_META_CHIP, as expected.\n");
	}
	value = NULL;
    } else {
	// We have the requested metadata
	if (status) {
	    *status = true;
	}
	value = item->data.V; // The requested metadata
    }
    return value;
}

void psMetadataPrint(psMetadata *md, int level)
{
    psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL);	// Iterator
    psMetadataItem *item = NULL;	// Item from metadata
    while (item = psMetadataGetAndIncrement(iter)) {
	// Indent...
	for (int i = 0; i < level; i++) {
	    printf(" ");
	}
	printf("%s", item->name);
	if (item->comment && strlen(item->comment) > 0) {
	    printf(" (%s)", item->comment);
	}
	printf(": ");
	switch (item->type) {
	  case PS_META_STR:
	    printf("%s", item->data.V);
	    break;
	  case PS_META_BOOL:
	    if (item->data.B) {
		printf("True");
	    } else {
		printf("False");
	    }
	    break;
	  case PS_META_S32:
	    printf("%d", item->data.S32);
	    break;
	  case PS_META_F32:
	    printf("%f", item->data.F32);
	    break;
	  case PS_META_F64:
	    printf("%f", item->data.F64);
	    break;
	  case PS_META_META:
	    printf("\n");
	    psMetadataPrint(item->data.V, level + 1);
	    break;
	  default:
	    psError(PS_ERR_IO, false, "Non-printable metadata type: %x\n", item->type);
	}
	printf("\n");
    }
    psFree(iter);

    return;
}


