#pragma once

#include "ElementRenderer.hpp"
#include "SwitchElement.hpp"

namespace ElementRenderer {

	//#########################################################################
	//#########################  LODElement  ################################
	//#########################################################################

	class LODElement:
		public SwitchElement
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Initialization
	//
	public:
		static void InitializeClass(Stuff::NotationFile *startup_ini);
		static void TerminateClass(Stuff::NotationFile *startup_ini);
		static ClassData *DefaultData;

		typedef SwitchElement BaseClass;

		static Stuff::Scalar s_Offset;
		static bool s_ShadeLODs;
		static Stuff::RGBAColor s_Shades[6];

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

	public:
		LODElement();
		~LODElement();

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

		void Save(Stuff::MemoryStream *stream);

		static HGOSHEAP s_Heap;

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Hierarchy
	//
	public:
		struct Entry
		{
			Stuff::Scalar
				m_nearSquared,
				m_farSquared;
		};

		void AttachLOD(
			WORD index,
			Element *element,
			const Entry &entry
		);

		void SetSize(WORD max_size);

	protected:
		void DetachChild(Element *child);

		Stuff::DynamicArrayOf<Entry> m_LODs;

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

		static DrawMethod DrawMethods[DrawStateCount];

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

	public:
		void CleanDamage();

		void ApplyDamage(
			const Stuff::LinearMatrix4D &damage_spot,
			Stuff::Scalar radius
		);

		void ApplyDamageDecal(
			const Stuff::LinearMatrix4D &damage_spot,
			Stuff::Scalar radius,
			MidLevelRenderer::MLRTexture *texture
		);
	};

}
