#pragma once

#include "ElementProxies.hpp"

namespace ElementProxies {

	class ElementGroupProxy;

	class ApplyDetailTexturesProcess;

	//
	//#########################################################################
	//#####################    ElementSceneProxy    ###########################
	//#########################################################################
	//
	class ElementSceneProxy:
		public Proxies::SceneProxy
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();
		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
		static ElementSceneProxy*
			MakeProxy(
				ElementRenderer::GroupElement *group,
				const char* texture_path
			)
				{return new ElementSceneProxy(group, texture_path);}

		static ElementSceneProxy*
			MakeProxy(ElementRenderer::GroupElement *group)
				{return new ElementSceneProxy(group);}

		void
			Destroy();

	protected:
		ElementSceneProxy(
			ElementRenderer::GroupElement *group,
			const char* texture_path
		);
		ElementSceneProxy(ElementRenderer::GroupElement *group);
		~ElementSceneProxy();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Process support
	//
	public:
		virtual void
			ApplyDetailTextures(ApplyDetailTexturesProcess *process);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Testing
	//
	public:
		void
			TestInstance() const;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Library functions
	//
	public:
		Proxies::StateLibrary*
			GetStateLibrary();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Bounding functions
	//
	// GetBoundingSphere should be used only after GetOBB has returned a false
	//
	public:
		void
			GetCentroid(Stuff::Point3D *center);
		bool
			GetOBB(Stuff::OBB *obb);
		void
			SetOBB(const Stuff::OBB &obb);
		bool
			GetBoundingSphere(Stuff::Sphere *sphere);
		void
			SetBoundingSphere(const Stuff::Sphere &sphere);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Scene functions
	//
	public:
		//
		// name functions
		//
		bool
			GetName(Stuff::MString *name);
		void
			SetName(const char* name);

		//
		// Gets the current number of children
		//
		unsigned
			GetChildCount();

		//
		// Polygon mesh child creation functions
		//
		Proxies::GroupProxy*
			AppendNewGroupProxy();
		Proxies::GroupProxy*
			InsertNewGroupProxy(Proxies::ChildProxy *before);

		Proxies::PolygonMeshProxy*
			AppendNewPolygonMeshProxy();
		Proxies::PolygonMeshProxy*
			InsertNewPolygonMeshProxy(Proxies::ChildProxy *before);
		//
		// Child traversal functions
		//
		Proxies::ChildProxy*
			UseFirstChildProxy();
		Proxies::ChildProxy*
			UseLastChildProxy();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Local implementation details
	//
	public:
		ElementRenderer::GroupElement*
			GetProxiedScene()
				{Check_Object(this); return proxiedScene;}

		Proxies::ChildProxy*
			InterpretElement(
				Proxies::GroupProxy *parent,
				Stuff::ChainIterator *iterator
			);

	protected:
		ElementRenderer::GroupElement
			*proxiedScene;
	};

}
