//
// Asura_Zone_Controller.h
//
// Created by Richard Rice - 25/01/05
// 
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __ASURA_ZONE_CONTROLLER_H__
#define __ASURA_ZONE_CONTROLLER_H__

class Asura_Zone;
class Asura_AABB_Tree;

class Asura_Zone_Controller
{
	friend class Tools_Zone_Editor;

public :
	Asura_Zone_Controller();
	virtual ~Asura_Zone_Controller();

	void Reset();

	//Get the current zone from camera position (or whatever)
	const Asura_Zone* GetZoneFromPosition(const class Asura_Vector_3& xPos) const;

    const Asura_Zone* GetZoneByID( const u_int uZoneID ) const;
    Asura_Zone* GetZoneByID( const u_int uZoneID );


	const Asura_Zone* GetZoneByIndex(int iIndex) const;
	Asura_Zone* GetZoneByIndex(int iIndex);

	int GetNumberOfZones() const {return m_iNumberOfZones;}

	//loading/saving (use of chunkbuffer or chunkstream versions will be dependent on derived class)
	//chunkbuffer functions
	virtual void InitialiseFromChunkBuffer(const char*& pcChunkBuffer);
#ifdef ASURA_TOOLS
	virtual void FillInChunkBuffer(char*& pcChunkBuffer);
	virtual int GetChunkBufferSize();
#endif 

	//loading/saving 
	virtual void ReadFromChunkStream(class Asura_Chunk_Stream& xStream);
#ifdef ASURA_TOOLS
	virtual void WriteToChunkStream(class Asura_Chunk_Stream& xStream);
#endif

#ifdef ASURA_TOOLS
	//invalidates the volume AABB tree and forces it to be recalculated when next needed
	void InvalidateVolumeTree(){m_bVolumeTreeValid = false;}
#endif

protected :
	// allocate a derived class from Asura_Zone
    // the bCreateFromLoad flag will be set if we are currently loading
    // (and hence will initialise the new zone with pre-set information)
	virtual Asura_Zone* AllocateZone( const bool bCreateFromLoad = false ) = 0;

	//If true then the position will be checked against the most recent zone found, and that
	//zone will be accepted if the position still lies within it
	//This may be undesirable if a means of prioritising in the case of overlaps is being used
	virtual bool UseMostRecentZoneByDefault() const {return true;}

	//If false then the zone controller will arbitrarily pick the first zone that it finds
	//that contains the position being checked. If true then it will continue searching
	//for other zones and use GetPriority() to determine the zone to use
	virtual bool UsePriorityForOverlaps() const {return false;}


private :

	void Initialise();
	void Shutdown();

	static bool VolumeTreeCallback(u_short usIndex);

#ifdef ASURA_TOOLS
	//for building the aabb tree
	void UpdateVolumeTree();
	//Need to be able to recalculate the volume tree in some const functions , so accidently lose the constness here.
	void UpdateVolumeTree() const {const_cast<Asura_Zone_Controller*>(this)->UpdateVolumeTree();}
	static bool FillVolumeTreeCallback(u_int uNumObjects,Asura_Bounding_Box* pxBoxes,Asura_Vector_3* pxCentres);
#endif


	int m_iNumberOfZones;
	Asura_Zone** m_ppxZones;

	int m_iNumberOfVolumes;//total number of volumes across all of the child zones
	Asura_AABB_Tree* m_pxVolumeTree;
	#ifdef ASURA_TOOLS
	bool m_bVolumeTreeValid;
	#endif

	mutable int m_iPreviousZoneIndex;
};


#endif //__ASURA_ZONE_CONTROLLER_H__
