#ifndef _COMMON_BLOCK_HPP_
#define _COMMON_BLOCK_HPP_
#ifndef _COMMON_EXCEPTION_HPP_
#include <common/except.hpp>
#endif
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif
#ifndef _COMMON_ARRAY_HPP_
#include <common/array.hpp>
#endif
#ifndef _MSC_VER
#ifdef _EXPAND_BLOCK_TEMPLATES_
#pragma option -Jgd
#endif
#endif

template <class T>
class Block;

template <class T>
class Container
{
friend class Block<T>;
public:
	Container<T> *next();
	void next(Container<T> *nextItem);
	Container<T> *prev();
	void prev(Container<T> *prevItem);
private:
	Container *mNext;
  Container *mPrev;
	T *mItem;
	Container(void);
	virtual ~Container();
};

template <class T>
class Block
{
public:
  class BlockBoundary{};
	typedef LONG Index;
	Block(void);
  Block(const Block<T> &someBlock);
	virtual ~Block(void);
	LONG size(void)const;
	void insert(const T *item);
	bool insertAfter(Index itemIndex,const T *item);
	void insert(Block<T> &newBlock);
	void remove(void);
	void remove(const T *item);
	void remove(Block<T> &removeBlock);
	void remove(Index itemIndex);
	void toArray(Array<T> &array);
	Block<T> &operator=(const Block<T> &someBlock);
	WORD operator==(const Block<T> &someBlock)const;
	T &operator[](LONG itemIndex);
	Block<T> &operator+=(const Block<T> &someBlock);
private:
	T &find(LONG itemIndex);
	LONG mSize;
	LONG mLastIndexReferenced;
	Container<T> *mLastObjectReferenced;
	Container<T> *mLastObjectInserted;
	Container<T> *mContainer;
};

template <class T>
inline
Block<T>::Block(void)
: mContainer(0), mSize(0), mLastIndexReferenced(-1),
  mLastObjectReferenced(0), mLastObjectInserted(0)
{
}

template <class T>
inline
Block<T>::Block(const Block<T> &someBlock)
: mContainer(0), mSize(0), mLastIndexReferenced(-1),
  mLastObjectReferenced(0), mLastObjectInserted(0)
{
  *this=someBlock;
}

template <class T>
inline
Block<T>::~Block()
{
	remove();
}

template <class T>
inline
LONG Block<T>::size(void)const
{
	return mSize;
}

template <class T>
inline
T & Block<T>::operator [](LONG itemIndex)
{
	if(itemIndex>=mSize)throw(BoundaryError());
	if(!mContainer)return *((T*)0);
	else if(itemIndex==mLastIndexReferenced&&-1!=mLastIndexReferenced&&mLastObjectReferenced)return *mLastObjectReferenced->mItem;
  else if(itemIndex==mLastIndexReferenced+1&&-1!=mLastIndexReferenced)
	{
		mLastIndexReferenced++;
		mLastObjectReferenced=mLastObjectReferenced->next();
		return *mLastObjectReferenced->mItem;
	}
  return find(itemIndex);
}

template <class T>
inline
void Block<T>::toArray(Array<T> &array)
{
  array.size(size());
	for(int index=0;index<size();index++)
	  array[index]=operator[](index);
}

// Container class methods

template <class T>
inline
Container<T>::Container()
: mNext(0), mPrev(0), mItem(0)
{
}

template <class T>
inline
Container<T>::~Container()
{
	if(mItem)delete mItem;
}

template <class T>
inline
Container<T> *Container<T>::next(void)
{
	return mNext;
}

template <class T>
inline
void Container<T>::next(Container<T> *nextItem)
{
	mNext=nextItem;
}

template <class T>
inline
Container<T> *Container<T>::prev(void)
{
	return mPrev;
}

template <class T>
inline
void Container<T>::prev(Container<T> *prevItem)
{
	mPrev=prevItem;
}
#if defined(_MSC_VER)
#include <common/block.tpp>
#endif
#endif

