//===========================================================================//
// File:	Map.hpp                                                   //
// Project: MUNGA           Brick: Interest Manager	                       //
// Contents: Interface specifications for interest manager						  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  -----------------------------------------------------------//
// 11/04/94  ECH  Initial coding.                                            //
// 11/29/94  JMA  Changed Identities to IDs                                  //
// 02/10/95  CPB  Added GaugeInterestType                                    //
// 08/25/97  ECH  Infrastructure changes.                                    //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc.                //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "Adept.hpp"
#include "Entity.hpp"
#include <ElementRenderer\GroupElement.hpp>

//#define BSP_BUG "jmalbert"

namespace ElementRenderer {class GridElement;}
namespace gosFX {class Light;}

namespace Adept {

	#if defined(BSP_BUG)
		extern bool debug_bsp;
	#endif

	class Zone;
	class Tile;
	class CollisionGrid;

	//########################################################################
	//########################    TerrainBSP    ##############################
	//########################################################################

	class TerrainBSP
	{
	public:
		WORD
			m_planeIndex,
			m_innerIndex,
			m_outerIndex;

		class CollisionQuery
			#if defined(_ARMOR)
				: public Stuff::Signature
			#endif
		{
		public:
			CollisionQuery(
				Stuff::Line3D *l,
				Stuff::Normal3D *n,
				Zone *z,
				Tile *t
			):
				m_line(l),
				m_normal(n),
				m_zone(z),
				m_tile(t)
					{}

			Stuff::Line3D
				*m_line;
			Stuff::Normal3D
				*m_normal;
			Zone
				*m_zone;
			Tile
				*m_tile;

			void
				TestInstance() const
					{}
		};

		bool
			TestLine(
				CollisionQuery *query,
				Stuff::Scalar enter,
				Stuff::Scalar leave
			);

		void
			TestInstance() const
				{}
	};

	//########################################################################
	//###########################    Tile    #################################
	//########################################################################

	class Tile:
		public ElementRenderer::GroupElement
	{
		friend class Zone;
		friend class TerrainBSP;
		friend class CollisionGrid;
		friend class TerrainTextureLogistic;
		friend class FiniteLight;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Initialization
	//
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();
		static ClassData
			*DefaultData;

		void
			TestInstance();
		static const Stuff::RGBAColor
			*s_GroundColor;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors/Destructors
	//
	protected:
		Tile(
			Zone *zone,
			BYTE row,
			BYTE column
		);
		~Tile();

		void
			Save(Stuff::MemoryStream *stream);

		ElementRenderer::Element
			*m_ground;
		BYTE
			m_row,
			m_column;
		Stuff::ChainOf<Entity*>
			m_collidees,
			m_colliders;

	

		Zone
			*m_zone;
		TerrainBSP
			*m_BSP;
		WORD
			m_BSPCount;
		Stuff::ChainOf<FiniteLight*>
			m_lights;
		bool
			m_lightsChanged;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Network damage culling 
	//
	
	protected:
		// this is just an array of all the original
		// things attached to this tile.
		// nothing is removed from it so it works 
		// all nice nice with the network.

		Stuff::DynamicArrayOf<Entity*>
			damagableEntityList;

		int
			m_DamageBitStart,
			m_damagableEntityCount;

	public:

		void
			AddEntityToDamagableList(Entity* entity);


		int 
			GetDamageBitStart()
		{
			Check_Object(this);
			return m_DamageBitStart;
		}

		int
			GetDamagableEntityCount()
		{
			Check_Object(this);
			return m_damagableEntityCount;
		}

		void 
			SetDamageBitStart(int bit)
		{
			Check_Object(this);
			m_DamageBitStart = bit;
		}

		void
			SetDamagableEntityCount(int count)
		{
			Check_Object(this);
			m_damagableEntityCount = count;
		}

		Entity *GetDamagableEntity(int id)
		{
			Check_Object(this);
			Verify (id < m_damagableEntityCount);
			return damagableEntityList[id];
		}


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Collision
	//
	protected:
		static void*
			TestTile(
				ElementRenderer::GridElement *grid,
				WORD cell,
				ElementRenderer::CollisionQuery *query,
				Stuff::Scalar enter,
				Stuff::Scalar leave
			);

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

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

		void
			UpdateLights();

	public:
		void
			TestInstance() const;
	};
}
