#include <stdlib.h>
#include <string.h>
#include "thing.h"
#include "lib.h"
#define DMID 19
#include "debug.h"

unsigned int thing_hash(char *string, int size);
int thing_cmp(const void **a, const void **b);
int thing_cmp_rev(const void **a, const void **b);

void thing_add(Thing **t, char *text) {
	unsigned int idx;
	AThing *p;	

	if (text==NULL) text = "(NULL)";
	if (*t == NULL) *t = calloc(1,sizeof(Thing));
	
	idx = thing_hash(text,THINGSZ);
	for(p = (*t)->table[idx]; p; p = p->next) {
		if (strcmpnc(p->text,text)==0) {
			p->count++;
			return ;
		}
	}
	p = keep_calloc(&(*t)->keep,1,sizeof(AThing));
	p->text = keep_strdup(&(*t)->keep,text);
	p->count = 1;

	p->next = (*t)->table[idx];
	(*t)->table[idx] = p;

	(*t)->items++;
}
void thing_free(Thing **t) {
//	AThing *p,*n;
//	int i;

	if (*t==NULL) return;
/*	for(i = 0; i < THINGSZ; i++) {
		for(p = (*t)->table[i]; p; p = n) {
			n = p->next;
			free(p->text);
			free(p);
		}
	}
	*/
	keep_freeall(&(*t)->keep);
	if ((*t)->sorted!=NULL) free((*t)->sorted);
	free(*t);
	*t = NULL;
}
void thing_sort(Thing *t, int ascending) {
	AThing *p;
	int i,j;
	
	if (t==NULL) return;
	if (t->sorted) return ;	
	t->sorted = (AThing **)calloc(t->items,sizeof(AThing));
	for(i = j = 0; i < THINGSZ; i++) {
		for(p = t->table[i]; p; p = p->next) {
			t->sorted[j++] = p;
		}		
	}
	qsort(t->sorted,t->items,sizeof(AThing *),(ascending)?(int(*)(const void *,const void *))thing_cmp:(int(*)(const void *,const void *))thing_cmp_rev);
}
char *thing_get(Thing *t, int n, int *count) {
	if (t==NULL) return NULL;
	if (t->sorted && n < t->items) {
		if (count) *count = t->sorted[n]->count;
		return t->sorted[n]->text;
	}
	return NULL;
}

/* Jesse's hashing fn - tested to be very good in almost all situations */
unsigned int thing_hash(char *string, int size) {
	unsigned int x = 0, i = 1;
	int r;
	while (*string != '\0') {
		x = (x + (*string) + i + size) * 1300493 % 11187503;
		string++; i++;
	}
	r = x%size;
	if (r<0) r = -r;
	return r;
}
int thing_cmp(const void **a, const void **b) {
	AThing *p1 = (AThing *)*a;
	AThing *p2 = (AThing *)*b;
	return p1->count - p2->count;
}
int thing_cmp_rev(const void **a, const void **b) {
	AThing *p1 = (AThing *)*a;
	AThing *p2 = (AThing *)*b;
	return p2->count - p1->count;
}
