#ifndef INCLUDED_RENDERER_SCENE
#define INCLUDED_RENDERER_SCENE

#include "Color.h"
#include <Math/Vector.h>

#include <memory>
#include <list>

//////////////////////////////////////////////////////////////
namespace Dubious {
namespace Renderer {

class Camera;
class OpenGLAttributes;
class VisibleObject;
class Billboard;
class BillboardRenderer;
typedef std::shared_ptr<Camera> CameraPtr;
typedef std::shared_ptr<VisibleObject> VisibleObjectPtr;
typedef std::shared_ptr<Billboard> BillboardPtr;
typedef std::shared_ptr<BillboardRenderer> BillboardRendererPtr;
typedef std::list<VisibleObjectPtr> VisibleObjectPtrList;
typedef std::list<BillboardPtr> BillboardPtrList;

/// @brief A Visible Scene
///
/// A Scene represents a collection of drawable object that will
///	be drawn.  It is really the top level construct for the Renderer
///	namespace.
class Scene 
{
public:
	/// @brief Constructor
	Scene();

	/// @brief Destructor
	~Scene();

	/// @brief A Light
	///
	/// This struct is just a simple grouping of the properties
	///	of a light.
	struct Light
	{
		Math::Vector	Position;
		Color			Ambient;
		Color			Diffuse;
		Color			Specular;
	};

	/// @brief Call this to render the scene
	void				Render( CameraPtr pCamera );

	/// @brief Add an object to the scene
	/// @param pObject - [in] the object
	void				AddObject( VisibleObjectPtr pObject );

	/// @brief Add a billboard to the scene
	/// @param pBillboard - [in] the billboard
	void				AddBillboard( BillboardPtr pBillboard );

	/// @brief Remove and object from the scene
	/// @param pObject - [in] the object
	void				RemoveObject( VisibleObjectPtr pObject );

	/// @brief Remove and billboard from the scene
	/// @param pBillboard - [in] the billboard
	void				RemoveBillboard( BillboardPtr pBillboard );

	/// @brief Remove all objects from the scene
	void				RemoveAllObjects();

	/// @brief Remove all billboards from the scene
	void				RemoveAllBillboards();

	/// @brief Accessor to the light
	Light&				SceneLight() { return m_SceneLight; }

	BillboardRendererPtr& BillboardRenderer() { return m_pBillboardRenderer; }
private:
	Scene( const Scene& );
	Scene& operator=( const Scene& );

	void				SetupLight( bool InShadow ) const;

	VisibleObjectPtrList m_Objects;
	BillboardPtrList	m_Billboards;
	Light				m_SceneLight;

	BillboardRendererPtr m_pBillboardRenderer;
};

}
}
#endif
