#ifndef BLUECORE_BUFFER_H
#define BLUECORE_BUFFER_H

#include <stdexcept>

namespace BlueCore
{
	template<class T>
	class Buffer
	{
	public:
	
		typedef T type;

	private:
	
		type *_buffer;
		unsigned int _count;
		
	public:
	
		/**
		 * default constructor
		 */
		Buffer() :
			_buffer( 0 ),
			_count( 0 )
		{
		}

		/**
		 * constructor with initial size
		 */
		Buffer( unsigned int count ) :
			_buffer( 0 ),
			_count( 0 )
		{
			create( count );
		}
	
		/**
		 * destructor
		 */
		virtual ~Buffer()
		{
			destroy();
		}

		/**
		 * create the buffer
		 */
		bool create( unsigned int count )
		{
			destroy();
		
			_buffer = new type[count];
		
			if( _buffer )
			{
				_count = count;
				return true;
			}
			else
			{
				return false;
			}
		}

		/**
		 * destroy the buffer
		 */
		void destroy()
		{
			delete [] _buffer;
			_buffer = 0;
			_count = 0;
		}

		void resize( unsigned int new_count )
		{
			type *new_buffer = new type[new_count];
			
			for( unsigned int i = 0; i<_count; i++ )
				new_buffer[i] = _buffer[i];
				
			destroy();
			
			_buffer = new_buffer;
			_count = new_count;
			 			
		}
		
		/**
		 * returns the item count
		 */		
		unsigned int count() const
		{
			return _count;
		}

		/**
		 * returns the buffer size in bytes
		 */
		unsigned int size() const
		{
			return _count * sizeof(type);
		}
		
		/**
		 * return a pointer to the data
		 */
		type *data()
		{
			return _buffer;
		}

		/**
		 * return a pointer to the(const) data
		 */
		const type *const_data() const
		{
			return _buffer;
		}

		/**
		 * array operator
		 */
		type &operator[](const unsigned int index)
		{
			if( index >= _count )
				throw std::range_error("Buffer::[] index_out_of_bound!");
			return _buffer[index];
		}

		type &item(const unsigned int index)
		{
			if( index >= _count )
				throw std::range_error("Buffer::[] index_out_of_bound!");
			return _buffer[index];
		}

		const type &const_item(const unsigned int index) const
		{
			if( index >= _count )
				throw std::range_error("Buffer::[] index_out_of_bound!");
			return _buffer[index];
		}
	};
}

#endif
