#pragma once

#include "Proxies.hpp"
#include "GenericProxy.hpp"

namespace Proxies {

	class SceneProxy;
	class GroupProxy;

	class BinSortProcess;
	class BurnLightsProcess;
	class CleanHierarchyProcess;
	class CopyProcess;
	class FindErrorsProcess;
	class FlattenHierarchyProcess;
	class SplitByStateProcess;
	class GetInfoProcess;
	class MakeSingleSidedProcess;
	class OptimizeFlatShadingProcess;

	//
	//#########################################################################
	//##########################    ChildProxy    #############################
	//#########################################################################
	//
	class _declspec(novtable) ChildProxy:
		public GenericProxy
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	protected:
		ChildProxy(
			ClassData *data,
			SceneProxy *scene,
			GroupProxy *parent
		);
		~ChildProxy();

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Process support
	//
	public:
		virtual bool
			BinSort(BinSortProcess *process);
		virtual void
			BurnLights(BurnLightsProcess *process);
		virtual bool
			CleanHierarchy(CleanHierarchyProcess *process);
		virtual int
			FindErrors(FindErrorsProcess *process);
		virtual void
			FindLights(BurnLightsProcess *process);
		virtual bool
			FlattenHierarchy(FlattenHierarchyProcess *process);
		virtual bool
			SplitByState(SplitByStateProcess *process);
		virtual bool
			MakeSingleSided(MakeSingleSidedProcess *process);
		virtual bool
			OptimizeFlatShading(OptimizeFlatShadingProcess *process);
		virtual void
			GetInfo(GetInfoProcess *process);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Position management functions
	//
	public:
		//
		// Position traversal functions
		//
		SceneProxy*
			GetSceneProxy()
				{Check_Object(this); return sceneProxy;}
		GroupProxy*
			GetParentGroupProxy()
				{Check_Object(this); return parentProxy;}

		virtual void
			TransferAndAppendToParentGroup(GroupProxy *parent) = 0;

		virtual ChildProxy*
			UseNextSiblingProxy()=0;
		virtual ChildProxy*
			UsePreviousSiblingProxy()=0;

	protected:
		SceneProxy
			*sceneProxy;
		GroupProxy
			*parentProxy;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Matrix functions
	//
	public:
		//
		// Matrix functions
		//
		virtual bool
			GetLocalToParent(Stuff::LinearMatrix4D *matrix) = 0;
		virtual void
			GetLocalToWorld(Stuff::LinearMatrix4D *matrix);
		virtual void
			SetLocalToParent(const Stuff::LinearMatrix4D &matrix) = 0;
		virtual void
			TransformLocalToParent(const Stuff::LinearMatrix4D &matrix);

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Polygon functions
	//
	public:
		virtual void
			GetCentroid(Stuff::Point3D *center) = 0;
	};

}
