#ifndef ARRAYLIST_H_
#define ARRAYLIST_H_

namespace system
{
	/*
	可変長の配列
	*/
	template <class T>
	class List
	{
		T *data_;
		size_t size_; // 配列のサイズ
		size_t elements_; // 要素の数
		size_t increase_; // 増加分
		void init(size_t size, size_t increase);
	public:
		static const unsigned int npos = static_cast<unsigned int>(-1);
		
		List(size_t size = 5, size_t increase = 5);
		~List();
	
		void add(T& element); // リファレンスじゃなくて良いのか？
		T& get(size_t pos);
		T& operator[](size_t pos);
		const T& operator[](size_t pos) const;
		T removeAt(size_t pos); // 指定した要素を削除
		T remove(const T& element); // 指定した要素を削除
		void removeAll(); // 全要素を削除
		size_t size() const; // 要素の数を返す
		bool empty() const;
		size_t indexOf(T element) const;
	};


// デフォルト引数付きコンストラクタ
template <class T>
List<T>::List(size_t size, size_t increase)
{
	//data_ = NULL;
	init(size, increase);
}

// デストラクタ
template <class T>
List<T>::~List()
{
	delete[] data_;
}

// 空だったらtrueを返す
template <class T>
inline bool List<T>::empty() const
{
	return elements_ == 0;
}

// 要素を追加する
template <class T>
void List<T>::add(T& element)
{
	if(size_ == elements_) {
		// 配列が満杯

		// 配列を増やす
		size_ += increase_;
		T *temp = new T[size_];

		size_t numElements = elements_;
		for(size_t i = 0; i < numElements; i++) {
			temp[i] = data_[i];
		}

		delete[] data_;
		data_ = temp;
		temp = NULL;
	}

	// 要素を追加する
	// コピー代入演算子の呼びだし
	data_[elements_] = element;
	elements_++;
}

// pos番目の要素を返す
template <class T>
T& List<T>::get(size_t pos)
{
	return data_[pos];
}

// 配列風
template <class T>
inline T& List<T>::operator [](size_t pos)
{
	return get(pos);
}

// 配列風
template <class T>
inline const T& List<T>::operator [](size_t pos) const
{
	return get(pos);
}

// サイズを返す
template <class T>
inline size_t List<T>::size() const
{
	return elements_;
}

// pos番目の要素を削除して、その要素のコピーを返す
template <class T>
T List<T>::removeAt(size_t pos)
{
	if(pos >= elements_) {
		return T();
	}

	// 削除対象の要素をコピー
	T temp = data_[pos];

	// 空きを埋める
	size_t numElements = elements_;
	for(size_t i = pos; i < numElements - 1; i++) {
		data_[i] = data_[i + 1];
	}
	elements_--;
	return temp;
}

// 指定した要素を削除して、その要素のコピーを返す
template <class T>
T List<T>::remove(const T& element)
{
	size_t numElements = elements_;
	for(size_t i = 0; i < numElements; i++) {
		if(data_[i] == element) {
			// 削除する要素が見つかった
			return (removeAt(i));
		}
	}
	return T();
}

// 全部削除
template <class T>
void List<T>::removeAll()
{
	delete[] data_;
	init(5, 5);
}

template <class T>
void List<T>::init(size_t size, size_t increase)
{
	// 要素数
	elements_ = 0;

	// サイズ、増加分を設定
	size_ = size;
	increase_ = increase;

	// 初期配列を作る
	data_ = new T[size_];
}

template <class T>
size_t List<T>::indexOf(T element) const
{
	// 要素を探す
	size_t numElements = elements_;
	for(size_t i = 0; i < numElements; i++) {
		if(data_[i] == element) {
			// 要素が見つかった
			return i;
		}
	}
	return npos;
}
}

#endif /*ARRAYLIST_H_*/
