#include <stdio.h>
#include <string.h>
#include <strings.h>

#include "psType.h"
#include "psError.h"
#include "psAbort.h"
#include "psTrace.h"
#include "psMetadata.h"
#include "psMetadataItemCompare.h"

bool psMetadataItemCompare(const psMetadataItem *compare, // Item to compare to the template
                           const psMetadataItem *template) // The template
{

    // First order checks
    if (! compare || ! template) {
        return false;
    }
    if (strcmp(compare->name, template->name)
            != 0) {
        return false;
    }


    #define COMPARE_CASE(TEMPLATENAME, TEMPLATETYPE, COMPARENAME, COMPARETYPENAME) \
case PS_TYPE_##COMPARETYPENAME: { \
        TEMPLATETYPE value = (TEMPLATETYPE)compare->data.COMPARENAME; \
        if (value != compare->data.COMPARENAME) { \
            return false; \
        } \
        return (template->data.TEMPLATENAME == value) ? true : false; \
    }

    #define TEMPLATE_CASE(TYPENAME, NAME, TYPE) \
case PS_TYPE_##TYPENAME: \
    switch(compare->type) { \
        COMPARE_CASE(NAME, TYPE, B  , BOOL); \
        COMPARE_CASE(NAME, TYPE, U8 , U8 ); \
        COMPARE_CASE(NAME, TYPE, U16, U16); \
        COMPARE_CASE(NAME, TYPE, U32, U32); \
        COMPARE_CASE(NAME, TYPE, S8 , S8 ); \
        COMPARE_CASE(NAME, TYPE, S16, S16); \
        COMPARE_CASE(NAME, TYPE, S32, S32); \
        COMPARE_CASE(NAME, TYPE, F32, F32); \
        COMPARE_CASE(NAME, TYPE, F64, F64); \
    default: \
        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Don't know how to compare types %x and %x\n", \
                compare->type, template->type); \
        return false; \
    }


    switch (template->type) {
        TEMPLATE_CASE(BOOL, B,   psBool)
        ;
        TEMPLATE_CASE(U8,   U8,  psU8 );
        TEMPLATE_CASE(U16,  U16, psU16);
        TEMPLATE_CASE(U32,  U32, psU32);
        TEMPLATE_CASE(S8,   S8,  psS8 );
        TEMPLATE_CASE(S16,  S16, psS16);
        TEMPLATE_CASE(S32,  S32, psS32);
        TEMPLATE_CASE(F32,  F32, psF32);
        TEMPLATE_CASE(F64,  F64, psF64);
    case PS_DATA_STRING:
        if (compare->type != PS_DATA_STRING) {
            return false;
        }
        psTrace("psLib.types", 10, "Comparing '%s' with '%s'\n",
                compare->data.str, template->
                data.str);
        return (strcasecmp(compare->data.V, template->
                           data.V) == 0) ? true : false;
    default:
        // Simply don't know how to compare more complex types.
        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Don't know how to compare types %x and %x\n",
                compare->type, template->type);
        return false;
    }

    psAbort(__func__, "Should never get here.\n");
    return false;
}
