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

#define HASH_TABLE_SIZE 32

// NOTE: the data is some value, which is on a certain 2D point (x,y)
typedef struct node
{
	// the data
	int x,y;
	float Value;

	// next entrie in the hashtable, if there were a collision
	struct node *Next;
}node;

#include "linked_list.h"

/*
 * Linked-list interface
 *
 * void list_add(node **Head, int Value, int x, int y);
 *
 * node *list_get(node **Head, int x, int y);
 *
 * void list_remove(node **Head, node *Node);
 *
 */

int hash(int x, int y)
{
	int Result = (x + y)%HASH_TABLE_SIZE;

	if(Result < 0)
		Result *= -1;
	return Result;
}

void hash_add(node **HashTable, float Value, int x, int y)
{
	int Hash = hash(x,y);
	node *Head = HashTable[Hash];
	list_add(&Head, Value, x, y);

	// Don't forget to update the Hashtables pointer to the head.
	HashTable[Hash] = Head;
}
node *hash_get(node **HashTable, int x, int y)
{
	int Hash = hash(x,y);
	node *Head = HashTable[Hash];
	node *Result = list_get(&Head, x, y);
	
	return Result;
}

void hash_remove(node **HashTable, int x, int y)
{
	int Hash = hash(x,y);
	node *Head = HashTable[Hash];
	node *Node = list_get(&Head, x, y);
	if(Node)
		list_remove(&Head, Node);
}

int main(int argc, char *argv)
{
	node *HashTable[HASH_TABLE_SIZE] = {};

	//payload D1 = {0, 0, 1.0, 0};

	hash_add(HashTable, 1.0, 1, 0);
        hash_add(HashTable, 3.0, 0, 1);
	hash_add(HashTable, 5.0, 3, -2);
        hash_add(HashTable, 7.0, 10, 3);

	// Note: Test adding with collisions
        node *Node = hash_get(HashTable, 1, 0);
	if(Node)
		printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y);
	else
		printf("Failed to add or find value 1 at position (1,0)\n");

	Node = hash_get(HashTable, 0, 1);
	int added01 = 0;
	if(Node)
	{	
		printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y);
		added01 = 1;
	}
	else
		printf("Failed to add or find value 3 at position (0,1)\n");

	Node = hash_get(HashTable, 3, -2);
	if(Node)
		printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y);
	else
		printf("Failed to add or find value 5 at position (-2,-2)\n");

	Node = hash_get(HashTable, 10, 3);
	if(Node)
		printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y);
	else
		printf("Failed to add or find value 7 at position (10,3)\n");

	// NOTE: Test removing element 
	if(added01)
	{
		hash_remove(HashTable, 0, 1);
		Node = hash_get(HashTable, 0, 1);
		if(!Node)
			printf("Succesfully removed entrie at position (0,1) from the HashTable\n");
		else
			printf("Failed to remove entrie at position (0,1)\n");
	}
}
