#pragma once

#include "ElementRenderer.hpp"
#include <gosFX\PointLight.hpp>

namespace gosFX
{
	//########################################################################
	//#############################  Light  ##################################
	//########################################################################

	class __declspec(novtable) Light:
		public Stuff::Plug
	{
	protected:
		Light(MidLevelRenderer::MLRLight* light);

	public:
		virtual ~Light();

		virtual void ChangeLight(gosFX::LightManager::Info *info);
		virtual void GetInfo(gosFX::LightManager::Info *info);

		MidLevelRenderer::MLRLight *m_light;
	};
}

namespace ElementRenderer {

	//############################################################################
	//########################  LightElementManager  #############################
	//############################################################################

	class LightElementManager:
		public gosFX::LightManager
	{
	public:
		static LightElementManager* &Instance;

		LightElementManager();
		~LightElementManager();

		virtual gosFX::Light* MakeLight(MidLevelRenderer::MLRLight *light)=0;

		void ChangeLight(
			gosFX::Light* light,
			Info *info
		);

		void DeleteLight(gosFX::Light *light);
	};

	//#########################################################################
	//#########################  LightElement  ################################
	//#########################################################################

	class LightElement:
		public Element
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Initialization
	//
	public:
		static void InitializeClass();
		static void TerminateClass();
		static ClassData *DefaultData;

		typedef Element BaseClass;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors/Destructors
	//
	protected:
		LightElement(
			Stuff::MemoryStream *stream,
			int version
		);

	public:
		LightElement();
		~LightElement();

		static LightElement* Make(
			Stuff::MemoryStream *stream,
			int version,
			ShapeHolder shapes=NULL
		);

		void Save(Stuff::MemoryStream *stream);

		static HGOSHEAP s_Heap;

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Hierarchy
	//
	protected:
		void AttachChild(Element *child);
		void DetachChild(Element *child);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Sync support
	//
	protected:
		void SetSyncState();

		void LightSync();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Collision
	//
	protected:
		bool CastCulledRay(CollisionQuery *query);
		Element* FindSmallestElementContainingCulled(SphereTest *test);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Drawing
	//
	protected:
		void SetDrawState();

		void Draw(
			CameraElement *camera,
			const StateChange *inherited_state,
			int clipping_state
		);

		int CountTriangles();

	public:
		gosFX::Light* GetLight()
			{Check_Object(this); return m_light;}
		void AdoptLight(gosFX::Light* light);

		LightElementManager::Info m_lightInfo;

	protected:
		gosFX::Light *m_light;
	};

}
