// ------------------------------------------------------------------------
/*
	author: Jaap Suter
   
	Copyright (C) Electronic Arts Canada Inc. 2002.  All rights reserved.	
*/
// ------------------------------------------------------------------------

/*! \file */

#ifndef REVEAL_CONTEXT_CONTAINER_H
#define REVEAL_CONTEXT_CONTAINER_H

#include <stddef.h>
#include <assert.h>
#include <math.h>

#include "reveal/context/object.h"
#include "reveal/context/bound_object.h"
#include "reveal/smart_ptr/scoped_ptr.h"

#include "reveal/global_enable.h"

namespace Reveal {

	class Renderer;
	class InputState;

	namespace Context {

// ------------------------------------------------------------------------------
/*!
	\brief Todo;
*/
// ------------------------------------------------------------------------------
class ContextContainer
{
public:

	ContextContainer() : mObjects(), mPickedObject( 0 ), mState( IDLE ) {}

	//Returns the offset of where the item was put (for removal)
	template < class T >
	size_t BindObjectToContext( float sphereRadius,
							  const Object::ClickAndHoldCallback& clickAndHoldCallback,
							  const Object::GetPositionCallback& getPosCallback,							  
							  T& object, BoundContext< T >& boundContext )
	{
		#ifdef REVEAL
			if ( IsRevealGloballyEnabled() )
			{
				SmartPtr::ScopedPtr< Object > o( new BoundObject< T >( object, sphereRadius, clickAndHoldCallback, getPosCallback, boundContext ) );
				for ( size_t i = 0; i < MAX_NUM_OBJECTS; ++i )
					if ( ! mObjects[ i ].Get() )
					{
						mObjects[ i ].Swap( o );
						return i;
					}
			}
		#endif
		return (size_t)(-1);
	}

	void Unbind (const size_t offset)
	{
		if (mObjects[ offset ].Get())
			mObjects[ offset ].Reset();
	}

	void Render( const Renderer& renderer ) const;
	bool Handle( const InputState& inputState, const Renderer& renderer );

private:

	ContextContainer( const ContextContainer& );			  // Not implemented, non copyable;
	ContextContainer& operator = ( const ContextContainer& ); // Not implemented, non assignable;

    enum { MAX_NUM_OBJECTS = 32 };
	SmartPtr::ScopedPtr< Object > mObjects[ MAX_NUM_OBJECTS ];
	Object* mPickedObject;

	enum
	{
		IDLE,
		PICKED,
		CLICKED_AND_HOLD,
	} mState;
};

	}; // Namespace Context

} // Namespace Reveal;

#endif
