#pragma once

#include <assert.h>
#include <stdio.h>

namespace RTL 
{

template< class Type > class List  
{
	Type*		m_pElement;
	int			m_nElement;
	int			m_nArraySize;	
public:
	void		Allocate(int nAlloc);
	void		SetSize(int nSize);
	void		Pack();
	void		Add(Type T);
	void		AddUnique(Type T);
	int			Contains(Type T);
	void		Remove(Type T);
	void		DelIndex(int nIndex);	
	void		Insert(Type T, int n);
	int			Find(Type T);
	void*		GetFirstPointer()
	{
		return &m_pElement[0];
	}

	Type&		operator[] (int i) 
	{
		assert( i>=0 && i< m_nElement);
		return m_pElement[i]; 
	}

	int			GetCount()
	{
		return m_nElement;
	};
	void		SetCount( int nElement )
	{
		m_nElement = nElement;
	};
	List();
	virtual ~List();

};

template< class Type > List< Type >::List()
{
	m_nArraySize = 0;
	m_nElement = 0;
	m_pElement = NULL;
}

template< class Type > List< Type >::~List()
{
	m_nElement = 0;
	delete [] m_pElement;
}
template< class Type > void List< Type >::Allocate(int nAlloc)
{
	assert( nAlloc > 0 );
	assert( nAlloc >= m_nElement );

	Type *pOldElement = m_pElement;
	m_nArraySize = nAlloc;
	m_pElement = new Type[ m_nArraySize ];
	assert( m_pElement );

	for(int i=0 ; i < m_nElement ; i++)
	{
		m_pElement[i]=pOldElement[i];
	}

	if( pOldElement )
		delete [] pOldElement;
}

template< class Type > void List< Type >::SetSize(int nSize)
{
	if( nSize==0 )
	{
		if( m_pElement )
			delete [] m_pElement;
	}
	else
	{
		Allocate(nSize);
	}
	m_nElement = nSize;
}

template< class Type > void List< Type >::Pack()
{
	Allocate(m_nElement);
}

template< class Type > void List< Type >::Add(Type T)
{
	assert( m_nElement <= m_nArraySize );
	if( m_nElement == m_nArraySize )
	{
		Allocate((m_nArraySize) ? m_nArraySize*2 : 16);
	}
	m_pElement[m_nElement++] = T;
}

template< class Type > int List< Type >::Contains(Type T)
{	
	int nSameElement = 0;
	for(int i=0;i<m_nElement;i++)
	{
		if( m_pElement[i] == T )
			nSameElement++;
	}
	return nSameElement;
}

template< class Type > void List< Type >::AddUnique(Type T)
{
	if( !Contains(T) )
		Add(T);
}

template< class Type > void List< Type >::DelIndex(int nIndex)
{
	assert( nIndex < m_nElement );
	m_nElement--;
	while( nIndex < m_nElement )
	{
		m_pElement[nIndex] = m_pElement[nIndex+1];
		nIndex++;
	}

}

template< class Type > void List< Type >::Remove(Type T)
{
	for( int i=0 ; i < m_nElement ; i++ )
	{
		if( m_pElement[i] == T )
			break;
	}

	DelIndex(i);

	for( i=0 ; i < m_nElement ; i++ )
	{
		assert( m_pElement[i] != T );
	}
}

template< class Type > void List< Type >::Insert(Type T, int n)
{
	if( m_nElement == 0)
		Add(T);
	else
	{
		Add(m_pElement[ m_nElement-1 ]);
		for( int i=0 ; i > n ; i-- )
		{
			m_pElement[i+1] = m_pElement[i];
		}
		m_pElement[n] = t;
	}
}

template< class Type > int List< Type >::Find(Type T)
{

	for( int i=0; i < m_nElement; i++ )
	{
		if( m_pElement[i] == T )
		{
			return i;
		}
	}
	return -1;
}

}


