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

#include "../../src/util/hashtable.h"
#include "../../src/util/memory.h"

static int err;

static int equalString(char *a, char *b)
{
	return strcmp(a, b) == 0;
}


/**
 * Builds hash kay/value hash table with value being int, and key being the
 * string representation of that int, then check if all the keys matches the
 * corresponding value.
 */
static void test_1()
{
	hashtable_Type *ht;
	int i;
	char s[10];
	char *key;
	int *value;
	
	
	//printf("string to int map:\n");
	
	ht = hashtable_new(
		(hashtable_getKeyHash) hashtable_getHashOfString,
		(hashtable_equalKeys) equalString);
	
	/* Create: key=string of the number, value=the number: */
	for(i = -500; i <= 500; i += 3){
		/* Builds a (key,value) pair of the form ("123",123): */
		sprintf(s, "%d", i);
		key = memory_strdup(s);
		value = memory_allocate(sizeof(int), NULL);
		*value = i;
		hashtable_put(ht, key, value);
	}
	
	/* Check if each key matches the value: */
	for(i = -500; i <= 500; i += 3){
		sprintf(s, "%d", i);
		value = hashtable_get(ht, s);
		assert(*value == i);
	}
	
	//hashtable_report(ht);
	
	memory_dispose(ht);
}


/**
 * Read my own source code line by line in a key/value hash table with key and
 * value being the line read, then remove entries whose value contains "printf"
 * and check if the resulting length of the hash table matches the removed
 * entries; finally, check that all the remaining entries actually do not
 * contain "printf" anymore.
 */
static void test_2()
{
	hashtable_Type *ht = hashtable_new(
		(hashtable_getKeyHash) hashtable_getHashOfString,
		(hashtable_equalKeys) equalString);
	char line[999];
	
	//printf("string to string map:\n");
	
	FILE *f = fopen(__FILE__, "rb");
	while( fgets(line, sizeof(line), f) != NULL ){
		if( hashtable_get(ht, line) == NULL )
			hashtable_put(ht, memory_strdup(line), memory_strdup(line));
	}
	fclose(f);
	
	f = fopen(__FILE__, "rb");
	while( fgets(line, sizeof(line), f) != NULL ){
		assert( strcmp(line, hashtable_get(ht, line)) == 0 );
	}
	fclose(f);
	
	
	// Remove entries containing "printf":
	int len_before = hashtable_length(ht);
	int len_after = len_before;
	char *key = hashtable_firstKey(ht);
	while(key != NULL){
		char *value = hashtable_get(ht, key);
		if( strstr("printf", value) != NULL ){
			hashtable_remove(ht, key);
			len_after--;
		}
		key = hashtable_nextKey(ht);
	}
	assert(len_after == hashtable_length(ht));
	
	// Check remaining values actually do not contain "printf" anymore:
	key = hashtable_firstKey(ht);
	while(key != NULL){
		char *value = hashtable_get(ht, key);
		assert( strstr("printf", value) == NULL );
		key = hashtable_nextKey(ht);
	}
	
	//hashtable_report(ht);
	
	memory_dispose(ht);
}


int main(int argc, char** argv)
{
	test_1();
	
	test_2();
	
	err += memory_report();
	return err == 0? 0 : 1;
}

