#pragma once

#include "MAXProxies.hpp"

#include <Stuff\stuff.hpp>
namespace MAXProxies {

	//
	//#########################################################################
	//###########################    MtlKeeper Helper class ###################
	//#########################################################################
	//
	class MtlKeeper 
	{
	public:
		bool	AddMtl(Mtl* mtl);
		int		GetMtlID(Mtl* mtl);
		int		Count();
		Mtl*	GetMtl(int id);
	
		Tab<Mtl*> mtlTab;
	};

	//
	//#########################################################################
	//###########################    BitmapKeeper Helper class ################
	//#########################################################################
	//
	class BitmapKeeper 
	{
	public:

		bool	AddBitmap(BitmapTex* bitmap);
		int		GetBitmapID(BitmapTex* bitmap);
		int		Count();
		BitmapTex*	GetBitmap(int id);
	
		Stuff::DynamicArrayOf<BitmapTex*> bitmapTab;
	};

	//
	//#########################################################################
	//###########################    NodeKeeper Helper class ##################
	//#########################################################################
	//
	class NodeKeeper 
	{
	public:
		bool	AddNode(INode* bitmap);
		int		GetNodeID(INode* bitmap);
		int		Count();
		INode*	GetNode(int id);
	
		Tab<INode*> nodeTab;
	};

	class MAXState;
	class MAXTexture;
	class MAXGroup;
	class MAXStateLibrary;


	//
	//#########################################################################
	//###########################    MAXScene    ###############################
	//#########################################################################
	//
	class MAXScene:
		public Proxies::SceneProxy
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	public:
		enum OpenMode {
			Overwrite,
			UseExisting
		};

		static MAXScene*
			MakeProxy(Interface *i,const char *str)
				{return new MAXScene(i,str);}

		void
			Destroy();

	protected:
		MAXScene(Interface *i,const char *);
		~MAXScene();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class Data Support
	//
	public:
		static ClassData
			*DefaultData;

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Library functions
	//
	public:
		Proxies::StateLibrary*
			GetStateLibrary();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Scene functions
	//
	public:
		//
		// name functions
		//
		bool
			GetName(Stuff::MString *name);
		void
			SetName(const char* name);

		//
		// Bounding functions
		//
		bool
			GetOBB(Stuff::OBB *obb);
		void
			SetOBB(const Stuff::OBB &obb);
		void
			SetBoundingSphere(const Stuff::Sphere &sphere);

		//
		// Gets the current number of children
		//
		unsigned
			GetChildCount();

		//
		// Polygon mesh child creation functions
		//
		Proxies::GroupProxy*
			AppendNewGroupProxy();
		Proxies::GroupProxy*
			InsertNewGroupProxy(Proxies::ChildProxy *before);

		Proxies::PolygonMeshProxy*
			AppendNewPolygonMeshProxy();
		Proxies::PolygonMeshProxy*
			InsertNewPolygonMeshProxy(Proxies::ChildProxy *before);

		Proxies::ChildProxy*
			AppendMatchingChildProxy(Proxies::ChildProxy *child);
		Proxies::ChildProxy*
			InsertMatchingChildProxy(
				Proxies::ChildProxy *child,
				Proxies::ChildProxy *before
			);

		//
		// Child traversal functions
		//
		Proxies::ChildProxy*
			UseFirstChildProxy();
		Proxies::ChildProxy*
			UseLastChildProxy();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	public:
		//
		// ambient color functions
		//
		void
			GetAmbientColor(Stuff::RGBColor *color);
		void
			SetAmbientColor(const Stuff::RGBColor &color);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Local implementation details
	//
	public:
		INode*
			GetProxiedScene()
				{Check_Object(this); return proxiedScene;}

		Interface *GetInterface()
			{Check_Object(this); return iPointer;}

		TimeValue GetTime()
			{Check_Object(this); return time;}

//		void
//			Write()
//				{Check_Object(this); mgWriteDb(mgGetCurrentDb());}
		void
			Close();

		Proxies::ChildProxy*
			InterpretRecord(
				MAXGroup *parent,
				INode *record,
				int index,
				bool auto_hierarchy
			);

		void 
			GetMeshProxies(INode* node, int& mesh_count);

		Proxies::ChildProxy* 
			CheckNodeForMesh(INode *child);

		MtlKeeper
			mtlList;

		BitmapKeeper
			bmpList;

		NodeKeeper 
			rootList;
		
		int GetBitmapCount()
			{Check_Object(this); return bmpList.Count();}

		int GetMtlCount()
			{Check_Object(this); return mtlList.Count();}

		int	GetNodeCount()
			{Check_Object(this); return nodeCount;}

		bool
			ValidElement(INode *node);

		Stuff::DynamicArrayOf<Proxies::ChildProxy *>
				meshProxies;

		INode 
			*FindRoot(INode *node);

		bool 
			notifiedOfError;

		Stuff::MString strHintFile;

		Stuff::Page *FindHint(Stuff::MString);

	protected:
		Stuff::NotationFile m_HintFile;

		INode 
			*GetNextChild(INode *parent);

		INode 
			*GetPreviousChild(INode *parent);

		int
			IndexFirstValidElement(INode *node);

		int
			IndexLastValidElement(INode *node);

		void 
			GetRootElements();

		int
			nodeCount;

		void 
			GetMaterials(INode* node, int& nodeCount);

		void
			GetBitmaps();

		Interface
			*iPointer;		

		TimeValue 
			time;

		INode
			*proxiedScene;


	};
}
