#include <stdio.h>
#include <stdlib.h>

#include "map.h"

#define error(str) printf("%s: %s\n", __FUNCTION__, (str)); exit (1);

struct skey {
    int k1, k2;
};

void test_int_keys()
{
    Map m;
    int key;
    AnyType a;
    struct MapWalk w;
    MapEl el;

    printf("Testing integer keys\n");

    printf("Creating map...");
    if (!(m = mapCreate(1024, sizeof(key)))) {
        error("mapCreate failed");
    }
    printf("passed\n");

    printf("Binding some keys...");
    for (key = 0; key < 100; key++) {
        if (! mapBind(m, &key, intToAny(100 - key))) {
            error("bind failed");
        }
    }
    printf("passed\n");

    printf("Resolving some keys...");
    for (key = 0; key < 100; key++) {
        if (mapResolve(m, &key, sizeof(key), &a) < 0) {
            error("could not resolve key");
        } 
        if (a.i != 100 - key) {
            error("key resolved to wrong value");
        }
    }
    printf("passed\n");

    /* Test some missing entries */
    printf("Resolving some invalid keys...");
    key = 101;
    if (mapResolve(m, &key, sizeof(key), &a) >= 0) {
        error("should not have been able to resolve key");
    } 
    key = -1;
    if (mapResolve(m, &key, sizeof(key), &a) >= 0) {
        error("should not have been able to resolve key");
    } 
    printf("passed\n");

    printf("Dumping the map...\n");
    mapWalkInit(&w, m);
    do {
        el = mapWalkNext(&w);
        if (el)
            printf("Key %d, value %d\n", *((int *) el->u.fixed.key), 
                   el->value.i);
    } while (el);

    printf("Deleting map\n\n");
    mapDelete(m);
}

void test_struct_keys()
{
    Map m;
    struct skey key, *k;
    int i;
    AnyType a;
    struct MapWalk w;
    MapEl el;

    printf("Testing struct keys\n");

    printf("Creating map...");
    if (!(m = mapCreate(1024, sizeof(key)))) {
        error("mapCreate failed");
    }
    printf("passed\n");

    printf("Map walk through empty map\n");
    mapWalkInit(&w, m);
    do {
        el = mapWalkNext(&w);
        if (el) {
            error("Found an element in an empty map");
        }
    } while (el);
    printf("passed\n");

    printf("Binding some keys...");
    for (i = 0; i < 100; i++) {
        key.k1 = i;
        key.k2 = i+1;
        if (! mapBind(m, &key, intToAny(100 - i))) {
            error("bind failed");
        }
    }
    printf("passed\n");

    printf("Resolving some keys...");
    for (i = 0; i < 100; i++) {
        key.k1 = i;
        key.k2 = i+1;
        if (mapResolve(m, &key, sizeof(key), &a) < 0) {
            error("could not resolve key");
        } 
        if (a.i != 100 - i) {
            error("key resolved to wrong value");
        }
    }
    printf("passed\n");

    /* Test some missing entries */
    printf("Resolving some invalid keys...");
    key.k1 = 10;
    key.k2 = 12;
    if (mapResolve(m, &key, sizeof(key), &a) >= 0) {
        error("should not have been able to resolve key");
    } 
    key.k1 = -1;
    key.k2 = 101;
    if (mapResolve(m, &key, sizeof(key), &a) >= 0) {
        error("should not have been able to resolve key");
    } 
    printf("passed\n");

    printf("Map walk through full map\n");
    mapWalkInit(&w, m);
    do {
        el = mapWalkNext(&w);
        if (el) {
            k = (struct skey *) el->u.fixed.key;
            printf("Key (%d, %d), value %d\n", k->k1, k->k2, el->value.i);
        }
    } while (el);

    printf("Deleting map\n\n");
    mapDelete(m);
}

int main()
{
    mapInit();
    test_int_keys();
    test_struct_keys();
    return 0;
}


