/* This code was written by:
Keir Lauritzen, Leon Song, and Guy Yardeni */

#include <stdio.h>
#include "hashmap.h"
#include "hashmap.c"
#include "wrapper.h"
#include <string.h>

void *map_list[1024];
int list_index = 0;

double strlen2(char str[]) {
	return (double)strlen(str);
}

void* create() {
	void *map;
	map = hashmap_new();
	map_list[list_index] = map;
	list_index++;
	return map;
}

int array_remove(void *map, char *key){
	return hashmap_remove(map, key);
}

char *malloc_string(char *string) {
	int len = strlen(string) + 1;
	char *str = (char *) malloc(len * sizeof(char));
	return str;
}

void destroy(void* map) {
	int i;
	hashmap_map *m = (hashmap_map *) map;
	int size = hashmap_length(m);

	if (hashmap_length(m) <= 0) {
		hashmap_free(map);
		return;
	}


	for (i = 0; i < m->table_size; i++) {
		if(m->data[i].in_use != 0){
			void *data = (void *) m->data[i].data;
			char *key = m->data[i].key;
			free(key);
			free(data);
		}
	}
	hashmap_free(map);
	return;
}

extern void destroy_all(){
	int i;
	for(int i=0; i < list_index; i++){
		void *map = map_list[i];
		destroy(map);
	}

}

char *get_key(void *map, char *key){
	int i;
	hashmap_map *m = (hashmap_map *) map;

	if (hashmap_length(m) <= 0) {
		hashmap_free(map);
		return NULL;
	}

	for (i = 0; i < m->table_size; i++) {
		if(m->data[i].in_use != 0){
			if (strcmp(m->data[i].key,key)==0) {
				char *key = m->data[i].key;
				return key;
			}
		}
	}
	return NULL;
}

int array_add_string(void* map, char* key, char* value) {
	int check;
	char *value_ptr = NULL;
	char *key_ptr = NULL;

	check = lookup(map, key);
	if (check == 1) {
		int error;
		char *old_key = get_key(map, key);
		char *string = NULL;
		void **data = (void **) &string;
		error = hashmap_get(map, key, data);

		hashmap_remove(map, key);
		free(string);
		free(old_key);
	}

	key_ptr = malloc_string(key);
	value_ptr = malloc_string(value);
	strcpy(value_ptr, value);
	strcpy(key_ptr, key);

	return hashmap_put(map, key_ptr, (void *)value_ptr);

}

int array_add_float(void* map, char* key, double value){
	int check;
	double *value_ptr;
	char *key_ptr = NULL;

	check = lookup(map, key);
	if (check == 1) {
		int error;
		char *old_key = get_key(map, key);
		double *float_ptr = NULL;
		void **data = (void **) &float_ptr;
		error = hashmap_get(map, key, data);

		hashmap_remove(map, key);
		free(float_ptr);
		free(old_key);
	}

	key_ptr = malloc_string(key); //only malloc if its a new key
	strcpy(key_ptr, key);
	value_ptr = (double *) malloc(sizeof(double));
	*value_ptr = value;


	return hashmap_put(map, key_ptr, (void *)value_ptr);
}

double array_retrieve_float(void *map, char *key){
	int error;
	double *float_ptr = NULL;
	void **data = (void **) &float_ptr;
	error = hashmap_get(map, key, data);
	return *float_ptr;
}

char *array_retrieve_string(void* map, char* key){
	int error;
	char *string = NULL;
	void **data = (void **) &string;
	error = hashmap_get(map, key, data);
	return string;
}

int lookup(void* map, char* key) {
	int error;
	void *lookup = NULL;
	void **data = (void **) &lookup;
	error = hashmap_get(map, key, data);
	if (error == MAP_OK){
		return 1;
	}
	return 0;
}
