#ifndef _COMMON_ARRAY_HPP_
#define _COMMON_ARRAY_HPP_
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif
#ifndef _COMMON_EXCEPTION_HPP_
#include <common/except.hpp>
#endif

template <class T>
class Array
{
public:
  Array(void);
	Array(const Array<T> &someArray);
	virtual ~Array();
	T &operator[](DWORD index);
	T &elementAt(DWORD index);
	Array<T> &operator=(const Array<T> &someArray);
	bool operator==(const Array<T> &someArray)const;
	DWORD size(void)const;
	void size(DWORD size);
	DWORD sizeBytes(void)const;
private:
  void destroy(void);
	void create(DWORD elements);

  T *mpArray;
	DWORD mElements;
};

template <class T>
inline
Array<T>::Array(void)
: mpArray(0), mElements(0)
{
}

template <class T>
inline
Array<T>::Array(const Array<T> &someArray)
: mpArray(0), mElements(0)
{
  *this=someArray;
}

template <class T>
inline
Array<T>::~Array()
{
  destroy();
}

template <class T>
inline
T &Array<T>::operator[](DWORD index)
{
  if(index>mElements)throw ArrayIndexOutOfBoundsException();
  return mpArray[index];
}

template <class T>
inline
Array<T> &Array<T>::operator=(const Array<T> &someArray)
{
  destroy();
  if(!someArray.size())return *this;
	size(someArray.size());
	for(unsigned index=0;index<size();index++)operator[](index)=((Array<T>&)someArray)[index];
	return *this;
}

template <class T>
inline
bool Array<T>::operator==(const Array<T> &someArray)const
{
  if(!someArray.size()||(size()!=someArray.size()))return FALSE;
  for(int index=0;index<size();index++)if(!(((Array<T>&)*this).operator[](index)==((Array<T>&)someArray)[index]))return FALSE;
	return TRUE;
}

template <class T>
inline
DWORD Array<T>::sizeBytes(void)const
{
  return mElements*sizeof(T);
}

template <class T>
DWORD Array<T>::size(void)const
{
  return mElements;
}

template <class T>
void Array<T>::size(DWORD size)
{
  create(size);
}

template <class T>
inline
void Array<T>::destroy(void)
{
  if(!mpArray)return;
	delete[] mpArray;
	mpArray=0;
	mElements=0;
}

template <class T>
inline
void Array<T>::create(DWORD elements)
{
  destroy();
	if(!elements)return;
	mpArray=new T[elements];
	if(0==mpArray)throw(NullError());
	mElements=elements;
}

template <class T>
inline
T &Array<T>::elementAt(DWORD index)
{
  if(index>mElements)throw ArrayIndexOutOfBoundsException();
  return mpArray[index];
}
#endif
