#ifndef VECTOR_HEADER
#define VECTOR_HEADER

template<class T> class Vector
{
public:
	typedef unsigned SizeType;
	class OutOfRange{};
	
	class Iterator
	{
	friend class Vector;
	private:
		unsigned current;
		T *array;
		Iterator(T* array, unsigned value) {this->array = array; this->current = value;}
	public:
		Iterator(const Iterator &iterator) {this->array = iterator.array; this->current = iterator.current;}
		
		bool operator == (const Iterator &iterator) const {return (this->current == iterator.current)
			&& (this->array == iterator.array);}
		bool operator != (const Iterator &iterator) const {return (this->current != iterator.current)
			|| (this->array != iterator.array);}
		Iterator& operator ++ () {current++; return *this;}
		Iterator& operator ++ (int) {current++; return *this;}
		T& operator * () const {return array[current];}
		T* operator -> () const {return array + current;}
	};

private:
	T *array;
	SizeType size;

public:
	Vector();
	Vector(const Vector &vector);
	~Vector();

	T& operator [] (const SizeType index);
	const T& operator [] (const SizeType index) const;
	Vector<T>& operator = (const Vector vector);

	Iterator Begin() {return Iterator(array, 0);}
	Iterator End() {return Iterator(array, size);}

	inline SizeType GetSize() const {return size;}

	void PushBack(const T elem);
	void Swap(const unsigned i1, const unsigned i2);
};

template<class T> Vector<T>::Vector()
{
	this->array = 0;
	this->size = 0;
}

template<class T> Vector<T>::Vector(const Vector &vector)
{
	this->size = vector.GetSize();
	this->array = new T[this->size];
	for (SizeType i = 0; i < this->size; i++)
		this->array[i] = vector.array[i];
}

template<class T> void Vector<T>::PushBack(const T elem)
{
	size++;
	T *tmp = array;
	array = new T[size];
	for (SizeType i = 0; i < size - 1; i++)
		array[i] = tmp[i];
	if (tmp != 0) delete [] tmp;
	array[size - 1] = elem;
}

template<class T> void Vector<T>::Swap(const unsigned i1, const unsigned i2)
{
	T tmp = (*this)[i1];
	(*this)[i1] = (*this)[i2];
	(*this)[i2] = tmp;
}

template<class T> Vector<T>::~Vector()
{
	if (this->array != 0) delete [] array;
}

template<class T> T& Vector<T>::operator [] (const SizeType index)
{
	if (index >= GetSize()) throw OutOfRange();
	return array[index];
}

template<class T> const T& Vector<T>::operator [] (const SizeType index) const
{
	if (index >= GetSize()) throw OutOfRange();
	return array[index];
}

template<class T> Vector<T>& Vector<T>::operator = (const Vector vector)
{
	size = vector.GetSize();
	array = new T[this->size];
	for (SizeType i = 0; i < size; i++)
		array[i] = vector.array[i];
		
	return *this;
}

#endif

