/**
 * \file BGDNetCollection.h
 * \brief Описание шаблона Collection
 */

#ifndef __BGDNetCollection_h__
#define __BGDNetCollection_h__

#include "BGDNetConfig.h"

#include <vector>
#include <assert.h>

namespace BGDNet
{

using std::vector;

/**
 * \class Collection
 * \brief Шаблон "Коллекция".
 *
 * Коллекция представляет собой упорядоченный набор объектов класса T.
 */
template<class T>
class BGDNET_API Collection
{
public:

  Collection( void );
  /**<
   * \brief Конструктор по умолчанию.
   * По умолчанию коллекция не содержит элементов.
   */

  Collection( const Collection& col );
  /**<
   * \brief Инициализатор копии.
   */

  Collection& operator =( const Collection& col );
  /**<
   * \brief Оператор присваивания.
   */

  ~Collection( void );
  /**<
   * \brief Деструктор.
   */

  int size( void ) const;
  /**<
   * \brief Возвращает размер коллекции.
   * @return Количество объектов в коллекции.
   */

  void resize( size_t sz, const T& x = T() );
  /**<
   * \brief Изменение размера коллекции.
   * @param sz Новый размер коллекции.
   * @param x Ссылка на элемент, значением которого заполняются
   * добавляемые элементы.
   */

  void add( const T& x );
  /**<
   * \brief Добавляет элемент в коллекцию.
   * Новые элементы добавляются в конец коллекции.
   * @param x Ссылка на добавляемый элемент.
   */

  void clear( void );
  /**<
   * \brief Удаляет все элементы из коллекции.
   */

  T& operator []( int n );
  /**<
   * \brief Доступ к элементам коллекции.
   * @param n Индекс элемента (начиная с 0)
   * @return Ссылка на n-й элемент коллекции
   */

  const T& operator []( int n ) const;
  /**<
   * \brief Доступ к элементам коллекции.
   * @param n Индекс элемента (начиная с 0)
   * @return Ссылка на n-й элемент коллекции
   */

  T& front( void );
  /**<
   * \brief Доступ к первому элементу коллекции.
   * @return Ссылка на первый элемент коллекции.
   */

  const T& front( void ) const;
  /**<
   * \brief Доступ к первому элементу коллекции.
   * @return Ссылка на первый элемент коллекции.
   */

  T& back( void );
  /**<
   * \brief Доступ к последнему элементу коллекции.
   * @return Ссылка на последний элемент коллекции.
   */

  const T& back( void ) const;
  /**<
   * \brief Доступ к последнему элементу коллекции.
   * @return Ссылка на последний элемент коллекции.
   */

private:

  vector<T>* m_pCont;
  /**<
   * \brief Указатель на вектор объектов класса T, еспользуемый в реализации.
   */
};

template<class T>
Collection<T>::Collection( void )
{
  m_pCont = new vector<T>;
}

template<class T>
Collection<T>::Collection( const Collection& col )
{
  m_pCont = new vector<T>(*col.m_pCont);
}

template<class T>
Collection<T>& Collection<T>::operator =( const Collection& col )
{
  if (this != &col) // избегаем присваивания самому себе
    *m_pCont = *col.m_pCont;
  return *this;
}

template<class T>
Collection<T>::~Collection( void )
{
  delete m_pCont;
}

template<class T>
int Collection<T>::size( void ) const
{
  return m_pCont->size();
}

template<class T>
void Collection<T>::resize( size_t sz, const T& x )
{
  m_pCont->resize(sz, x);
}

template<class T>
void Collection<T>::add( const T& x )
{
  m_pCont->push_back(x);
}

template<class T>
void Collection<T>::clear( void )
{
  m_pCont->clear();
}

template<class T>
T& Collection<T>::operator []( int n )
{
  assert(0 <= n && n < size());
  return m_pCont->at(n);
}

template<class T>
const T& Collection<T>::operator []( int n ) const
{
  assert(0 <= n && n < size());
  return m_pCont->at(n);
}

template<class T>
T& Collection<T>::front( void )
{
  assert(size() > 0);
  return m_pCont->front();
}

template<class T>
const T& Collection<T>::front( void ) const
{
  assert(size() > 0);
  return m_pCont->front();
}

template<class T>
T& Collection<T>::back( void )
{
  assert(size() > 0);
  return m_pCont->back();
}

template<class T>
const T& Collection<T>::back( void ) const
{
  assert(size() > 0);
  return m_pCont->back();
}

} // namespace BGDNet

#endif //__BGDNetCollection_h__
