
#include <PalmUtils.h>
#include <PalmOS.h>

#include "vector.h"
#include "data_structures.h"

Err InitVector(Vector *v, Int32 type) {
	v->data = MemHandleNew(ALLOC_SIZE);
	if (v->data == 0) {
		return -1;
	}
	v->used_size = 0;
	v->element_size = sizeof(MemHandle);
	v->num_elements = 0;
	v->type = type;
	return 0;
}

Err DeleteVector(Vector v) {
  Err err = 0;
  MemHandle mh;
  UInt32 iNumElements = v.num_elements;
  UInt32 i;
  
	for (i = 0; i < iNumElements; i ++) {
		if ((err =GetElement(&v, &mh, 0)) != 0) {
			return err;
		}
		if (v.type == Channel) {
			if ((err = DeleteChannelInfoMemHandle(mh)) != 0) {
				return err;
			}
		} else if (v.type == Group) {
			if ((err = DeleteGroupInfoMemHandle(mh)) != 0) {
				return err;
			}
		} else if (v.type == Machine) {
			if ((err = DeleteMachineInfoMemHandle(mh)) != 0) {
				return err;
			}			
		} else if (v.type == Merge) {
			if ((err = DeleteMergeInfoMemHandle(mh)) != 0) {
				return err;
			}			
		}
		DeleteElement(&v, 0);
	}
	MemHandleFree(v.data);
	
	return err;
}
Err ResizeVector(Vector *v) {
	return MemHandleResize(v->data, MemHandleSize(v->data) + ALLOC_SIZE);
}

Err AddElement(Vector *v, MemHandle newElement, UInt32 pos) {
  UInt32 current_size = MemHandleSize(v->data);
  Err err = 0;
  MemPtr vDataPtr;
  UInt32 offset = v->element_size * pos;
  
	if ((v->used_size + v->element_size) > current_size) {
		if ((err = ResizeVector(v)) != 0) {
			return err;
		}
	}
	vDataPtr = MemHandleLock(v->data);
	if (pos < v->num_elements) {
		if ((err = MemMove(vDataPtr + offset + v->element_size, 
			vDataPtr + offset, 
			(v->num_elements - pos) * v->element_size)) != 0) {
				return err;
		}
	}
//	if ((err = MemMove(vDataPtr + offset, &newElement, v->element_size)) != 0) {
//		return err;
//	}
	*((MemHandle *)(vDataPtr + offset)) = newElement;
	v->used_size += v->element_size;
	v->num_elements ++;
	MemHandleUnlock(v->data);
	return err;
}

Err GetElement(Vector *v, MemHandle *retVal, UInt32 pos) {
  Err err = 0;
  MemPtr vDataPtr;
  UInt32 offset = pos * v->element_size;
  
	if (pos >= v->num_elements) {
		return -1;
	}
	vDataPtr = MemHandleLock(v->data);
	if ((err = MemMove(retVal, vDataPtr + offset, v->element_size)) != 0) {
		return err;
	}
	MemHandleUnlock(v->data);
	return err;
}

Err UpdateElement(Vector *v, MemHandle updatedElement, UInt32 pos) {
  Err err = 0;
  MemPtr vDataPtr;
  UInt32 offset = v->element_size * pos;

	if (pos >= v->num_elements) {
		return -1;
	}
	vDataPtr = MemHandleLock(v->data);
	if ((err = MemMove(vDataPtr + offset, &updatedElement, v->element_size)) != 0) {
		return err;
	}
	MemHandleUnlock(v->data);
	return err;
	
}

Err DeleteElement(Vector *v, UInt32 pos) {
  Err err = 0;
  MemPtr vDataPtr;
  UInt32 offset = v->element_size * pos;
  
	if (pos >= v->num_elements) {
		return -1;
	}
	vDataPtr = MemHandleLock(v->data);
	if ((err = MemMove(vDataPtr + offset, 
			vDataPtr + offset + v->element_size, 
			(v->num_elements - pos - 1) * v->element_size)) != 0) {
		return err;
	}
	MemHandleUnlock(v->data);
	v->used_size -= v->element_size;
	v->num_elements --;
	return err;

}

Int32 GetElementLocation(Vector *v, MemHandle check) {
  UInt32 i;
  MemHandle mhLocal;
  
	for (i = 0; i < v->num_elements; i ++) {
		if (GetElement(v, &mhLocal, i) != 0) {
			return -1;
		}
		if (mhLocal == check) {
			return i;
		}	
	}
	return -1;	
}