// Container class

#ifndef _CCONTAINER_H_
#define _CCONTAINER_H_

#include <assert.h>

// This is a container class, used to keep track of free slots of items

template <class ITEM>
class CContainer{
public:

	// Member methods
	CContainer(){};                                  // Empty default constructor
	~CContainer();                                   // Deconstructor frees all the memory (Including items!)

	int initContainer(int size);                     // Initilizes the dynamic arrays

	ITEM getItemAt(int index);                       // Returns the item at index
	bool isSlotFree(int index);                      // Returns true if the slot at index is free

	int getFreeSlot();                               // Returns the index of the first free slot
	void insertToContainer(ITEM item, int index);   // Inserts an item into the container at index

	int removeItemAt(int index);                     // Removes the item at index (Return values: 0 - Success. 1 - No item at index initilized. 2 - index out of bounds)

protected:
	
	// Member variables
	ITEM *items;                                     // Dynamic array of items in this container
	bool *isFree;                                    // Dynamic array of bools used to determine what slots are free
	int elements;                                    // Elements currently used in the container
	int totalSize;                                   // Total size of the container

};

// Deconstructor frees all the memory (Including items!)
template <class ITEM> CContainer<ITEM>::~CContainer(){
	if(totalSize){
		delete [] items;
		delete [] isFree;
	}else{
		delete items;
		delete isFree;
	}
}

// Initilizes the dynamic arrays
template <class ITEM> int CContainer<ITEM>::initContainer(int size){
	if(size <= 0)
		return 0;

	items = new ITEM[size];
	isFree = new bool[size];

	for(int i = 0; i < size; i++){
		isFree[i] = true;
		items[i] = 0x00000000;
	}

	totalSize = size;

	return 1;
}
// Returns the item at index
template <class ITEM> ITEM CContainer<ITEM>::getItemAt(int index){
	assert(totalSize > 0);
	assert(index < totalSize && index >= 0);	// First time I use asserts. Let's see how this works out
	assert(!isFree[index]);
	
	return items[index];
}

// Returns true if the slot at index is free 
template <class ITEM> bool CContainer<ITEM>::isSlotFree(int index){
	assert(totalSize > 0);
	assert(index < totalSize && index >= 0);

	// Return the value of isFree at index
	return isFree[index];
}

// Returns the index of the first free slot
template <class ITEM> int CContainer<ITEM>::getFreeSlot(){
	assert(totalSize > 0);

	// Loop through the entire isFree array, and return on the first true found
	for(int i = 0; i < totalSize; i++){
		if(*isFree[i])
			return i;
	}
	// If no free slot is found, return error
	return -1;
}

// Inserts an item into the container at index
template <class ITEM> void CContainer<ITEM>::insertToContainer(ITEM item, int index){
	assert(totalSize > 0);
	assert(index < totalSize && index >= 0);	// First time I use asserts. Let's see how this works out

	// The slot isn't free.. Oh well, let's delete whatever's there
	if(!isFree[index])
		removeItemAt(index); // Insert remove call

	items[index] = item;
	isFree[index] = false;

}

template <class ITEM> int CContainer<ITEM>::removeItemAt(int index){
	assert(totalSize > 0);
	
	if(index > totalSize)
		return 2;

	if(isFree[index])
		return 1;

	delete items[index];
	items[index] = 0x00000000;
	isFree[index] = true;

	return 0;

};

#endif