//
//strarray.c
//
//Handling routines for arrays of strings.
//
//Currently only handles arrays of string pairs
//
//
//-UserX 2001/11/04

#include <string.h>
#include "misc/compat.h"
#include "base/array.h"
#include "base/strarray.h"
#include "base/str.h"

StringPair stringpairblank = {"", ""};

char *stringnull = NULL;

void saStringFree(char **str) {
	stringFree(*str);
}

//StringArrayHandle *makeStringArray(void) {
StringArrayHandle *saMake(void) {
	return (StringArrayHandle *)arrayMake(sizeof(char *), 0, &stringnull, NULL, (ArrayFuncDelete) saStringFree);
}

//void freeStringArray(StringArrayHandle *array) {
void saFree(StringArrayHandle *array) {
	arrayFree((ArrayHandle *) array);
}


//copy a full string array
StringArrayHandle *saCopy(StringArrayHandle *sa) {
	int i;
	StringArrayHandle *nsa = saMake();
	if(sa == NULL) {
		return nsa;
	}
	//todo: maybe: this could be made more efficient
	for(i = 0; i < sa->size; i++) {
		saAppendCopy(nsa, sa->data[i]);
	}
	return nsa;
}

//deletes count elements and then shrinks the array down
void saDeleteMany(StringArrayHandle *array, int first, int count) {
	arrayDelete((ArrayHandle *) array, first, count);
}

//deletes one element and shrinks the array down
void saDelete(StringArrayHandle *array, int i) {
	saDeleteMany(array, i, 1);
}

//Adds count new elements to an array.
void saExpand(StringArrayHandle *array, int count) {
	arrayAddElements((ArrayHandle *) array, count);
}

void saAppend(StringArrayHandle *array, char *str) {
	saExpand(array, 1);
	array->data[array->size - 1] = str;
}

//Copies the string before storing
void saAppendCopy(StringArrayHandle *array, char *str) {
	saExpand(array, 1);
	array->data[array->size - 1] = stringCopy(str);
}

StringArrayHandle *saMakeFromSplitString(char *instring, char *splitstring) {
	//StringArrayHandle *sa = makeStringArray();
	StringArrayHandle *sa = saMake();
	char *s;
	char *p;
	if(isStringBlank(instring)) {
		return sa;
	}
	if(isStringBlank(splitstring)) {
		saAppendCopy(sa, instring);
		return sa;
	}
	s = stringCopy(instring);

	for(p = stringSplit(s, splitstring); !isStringBlank(s); p = stringSplit(s, splitstring)) {
		saAppend(sa, p);
	}
	saAppend(sa, p);
	stringFree(s);
	return sa;
}

char *saImplode(StringArrayHandle *sa, char *sep) {
	int i;
	char *s;
	char *ss;
	int l = 0;
	if(sa == NULL) {
		return stringBlank();
	}
	if(sa->size == 0) {
		return stringBlank();
	}
	if(sep == NULL) {
		sep = "";
	}
	for(i = 0; i < sa->size; i++) {
		l += stringLength(sa->data[i]);
	}
	l += stringLength(sep) * (sa->size - 1);
	s = stringMake(l);
	ss = s;
	if(sa->data[0] != NULL) {
		strcpy(ss, sa->data[0]);
		ss += strlen(sa->data[0]);
	}
	for(i = 1; i < sa->size; i++) {
		strcpy(ss, sep);
		ss += strlen(sep);
		if(sa->data[i] != NULL) {
			strcpy(ss, sa->data[i]);
			ss += strlen(sa->data[i]);
		}
	}
	return s;
}

//returns non-zero if any string in the first array matches any string in the second array
//case insensitive
int saMatchAny(StringArrayHandle *sa1, StringArrayHandle *sa2) {
	int i;
	int j;
	if(sa1 == NULL) {
		return 0;
	}
	for(i = 0; i < sa1->size; i++) {
		for(j = 0; j < sa2->size; j++) {
			if(stringCaseCompare(sa1->data[i], sa2->data[j]) == 0) {
				return 1;
			}
		}
	}
	return 0;
}

//does stringTrim() on all strings in a string array
void saTrim(StringArrayHandle *sa, char *what) {
	int i;
	for(i = 0; i < sa->size; i++) {
		sa->data[i] = stringTrim(sa->data[i], what);
	}
}

StringPair stringPairCopy(StringPair *sp) {
	StringPair nsp;
	nsp.key = stringCopy(sp->key);
	nsp.val = stringCopy(sp->val);
	return nsp;
}

void stringPairFree(StringPair *sp) {
	stringFree(sp->key);
	stringFree(sp->val);
}

StringPair stringPairMake(char *key, char *val) {
	StringPair sp;
	sp.key = key;
	sp.val = val;
	return sp;
}

StringPair stringPairMakeCopy(char *key, char *val) {
	StringPair sp;
	sp.key = stringCopy(key);
	sp.val = stringCopy(val);
	return sp;
}

//creates an array for StringPairs
//StringPairArrayHandle *makeStringPairArray(void) {
StringPairArrayHandle *spaMake(void) {
	return (StringPairArrayHandle *)arrayMake(sizeof(StringPair), 0, &stringpairblank, NULL, (ArrayFuncDelete) stringPairFree);
}

//releases an array of StringPairs
//void freeStringPairArray(StringPairArrayHandle *array) {
void spaFree(StringPairArrayHandle *array) {
	arrayFree((ArrayHandle *) array);
}

StringPair spaGet(StringPairArrayHandle *array, int i) {
	if(i < 0 || i >= array->size) {
		return stringpairblank;
	}

	return array->data[i];
}

//assumes the strings in sp are for it keep and release when finished. (use *Copy if not)
void spaSet(StringPairArrayHandle *array, StringPair sp, int i) {
	if(i < 0 || i >= array->size) {
		return;
	}
	stringPairFree(&array->data[i]);
	array->data[i] = sp;
	
}

//Copies the strings of sp before storing
void spaSetCopy(StringPairArrayHandle *array, StringPair sp, int i) {
	spaSet(array, stringPairCopy(&sp), i);
}

//deletes count elements and then shrinks the array down
void spaDeleteMany(StringPairArrayHandle *array, int first, int count) {
	arrayDelete((ArrayHandle *) array, first, count);
	//int i;
	///todo: range checking

	//for(i = first; i < first + count; i++) {
	//	stringPairFree(&array->data[i]);
	//}
	//for(i = first + count; i < array->size; i++) {
	//	array->data[i - count] = array->data[i - count];
	//}
	//arrayDeleteElements((ArrayHandle *) array, count);
}

//deletes one element and shrinks the array down
void spaDelete(StringPairArrayHandle *array, int i) {
	spaDeleteMany(array, i, 1);
}

//Adds count new elements to an array.
void spaExpand(StringPairArrayHandle *array, int count) {
	arrayAddElements((ArrayHandle *) array, count);
}

//Add a string pair to the end of the array.
//assumes the strings in sp are for it keep and release when finished. (use *Copy if not)
void spaAppend(StringPairArrayHandle *array, StringPair sp) {
	spaExpand(array, 1);
	array->data[array->size - 1] = sp;
}

//Copies the strings of sp before storing
void spaAppendCopy(StringPairArrayHandle *array, StringPair sp) {
	spaExpand(array, 1);
	array->data[array->size - 1] = stringPairCopy(&sp);
}


//todo: make proper array handling functions StringIntPairs

//Searchs a normal array of StringIntPairs for the string match
//does case insensitive compares
int stringIntPairSearch(StringIntPair *array, char *match) {
	if(array == NULL) {
		return -1;
	}
	if(match == NULL) {
		return -1;
	}
	while(array->key != NULL) {
		if(strcasecmp(array->key, match) == 0) {
			return array->val;
		}
		array += 1;
	}
	return -1;
}
