//===========================================================================//
// 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 "EntityClassData.hpp"

namespace ElementRenderer {class GridElement;}

namespace Adept {

	class Map;
	class Zone__ResourceData;

	//##########################################################################
	//####################    Map::CreateMessage    ############################
	//##########################################################################

	class Map__CreateMessage:
		public Entity__CreateMessage
	{
	public:
		ResourceID
			m_propStreamResourceID;

		Map__CreateMessage(
			size_t length,
			int priority,
			int message_flags,
			Stuff::RegisteredClass::ClassID class_id,
			int replicator_flags,
			const ResourceID& instance_id,
			const Stuff::LinearMatrix4D &creation_matrix,
			Stuff::Scalar age,
			int execution_state,
			int name_id,
			int entity_alignment,
			const ResourceID &prop_stream_id
		):
			Entity__CreateMessage(
				length,
				priority,
				message_flags,
				class_id,
				replicator_flags,
				instance_id,
				creation_matrix,
				age,
				execution_state,
				name_id,
				entity_alignment
			),
			m_propStreamResourceID(prop_stream_id)
				{}

		static void
			ConstructCreateMessage(Script *script);
	};

	//##########################################################################
	//#####################    Mover::ModelResource    #########################
	//##########################################################################

	class Map__GameModel:
		public Entity__GameModel
	{
	public:
		ResourceID
			m_gridElementResourceID,
			m_zoneArrayResourceID,
			m_textureDataResourceID,
			m_damageCraterResourceID,
			m_tcfResourceID,
			m_culturalDataResourceID;
		Stuff::Scalar
			m_waterLevel;
		char m_HudMap[128];

	//	enum {
	//		GridElementResourceIDAttributeID = Entity__GameModel::NextAttributeID,
	//		ZoneArrayResourceIDAttributeID,
	//		DamageCraterResourceID,
	//		NextAttributeID
	//	};
		enum {
			DamageCraterResourceAttributeID = Entity__GameModel::NextAttributeID,
			NextAttributeID
		};

		static bool
			ReadAndVerify(
				Map__GameModel *model,
				ModelAttributeEntry *attribute_entry,
				const char *data,
				char **error,
				int error_buffer = 128
			);

		static void
			ConstructGameModel(Script *script);
	};

	//##########################################################################
	//###########################    Map    ####################################
	//##########################################################################

	class Map:
		public Entity
	{
		friend class Zone;
		friend class Mission;

	public:
		static void
			InitializeClass(Stuff::NotationFile *startup_ini);
		static void
			TerminateClass(Stuff::NotationFile *startup_ini);
		static ClassData
			*DefaultData;

		typedef Map__CreateMessage CreateMessage;
		typedef Map__GameModel GameModel;

		static Map*
			GetInstance()
		{
			return reinterpret_cast<Map *>( GlobalPointers::GetGlobalPointer(MapGlobalPointerIndex));
		};


		static int
			LoadRadius;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		Replicator::CreateMessage*
			SaveMakeMessage(Stuff::MemoryStream *stream, ResourceFile *res_file);

	protected:
		Map(
			ClassData *class_data,
			const CreateMessage *message,
			ReplicatorID *base_id,
			ElementRenderer::GridElement *element,
			int slot_count
		);
		~Map();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Ownership
	//
	public:
		void
			AddChild(Entity *entity);
		void
			RemoveChild(Entity *entity);

		void
			UpdateZone(Entity *entity);
		int
			FindZone(const Stuff::Point3D &where);
		void
			GetMapExtents(
				Stuff::Scalar *min_z,
				Stuff::Scalar *max_z,
				Stuff::Scalar *min_x,
				Stuff::Scalar *max_x
			);
		Stuff::Scalar
			GetColumnZoneScale() {return m_columnZoneScale;}
		Stuff::Scalar
			GetRowZoneScale() {return m_rowZoneScale;}

		void
			WorldToZoneCoords(Stuff::Scalar& x, Stuff::Scalar& y) const;

	protected:
		void
			ChildPreCollisionChanged(Entity *entity);

		WORD
			m_zoneCount;
		BYTE
			m_columnZoneCount,
			m_rowZoneCount;
		Stuff::Scalar
			m_columnZoneOrigin,
			m_columnZoneScale,
			m_rowZoneOrigin,
			m_rowZoneScale;
		Zone
			*m_zones,
			*m_renderOrigin;

		ChainOf<Zone*>
			m_executingZones,
			m_renderedZones;

		Resource
			m_zonesResource;
		Zone__ResourceData*
			GetZoneResourceData(unsigned index);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Game Model Support
	//
	public:
		const GameModel*
			GetGameModel()
				{
					Check_Object(this);
					return Cast_Pointer(const GameModel*,gameModelResource.GetPointer());
				}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Renderer Support
	//
	public:
		ElementRenderer::GridElement*
			GetElement()
				{
					Check_Object(this);
					return
						Cast_Pointer(
							ElementRenderer::GridElement*,
							entityElement
						);
				}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Execution support
	//
	public:
		void
			PreCollisionExecute(Stuff::Time till);
		void
			SyncMatrices(bool update_locator);
		void
			UpdateRenderOrigin(const Stuff::Point3D &location);
		void
			ActivateZones();

		ResourceID
			propListResourceID;

	protected:
		DynamicArrayOf<Entity*>
			m_executionSlots;
	};
}
