// ----------------------------------------------------------------------- //
//
// MODULE  : HierarchicalButeMgr.h
//
// PURPOSE : HierarchicalButeMgr definition - Base class for all hierarchical bute mgrs (have Parent property)
//
// CREATED : 3/3/00
//
// ----------------------------------------------------------------------- //

#ifndef __HIERARCHICAL_BUTE_MGR_H__
#define __HIERARCHICAL_BUTE_MGR_H__

#include "GameButeMgr.h"



class CHierarchicalButeMgr : public CGameButeMgr
{
	enum MicrosoftHackForInlineConstant
	{
		g_nMaxResursionLevel = 100
	};

public:

	virtual ~CHierarchicalButeMgr() {}

	virtual DBOOL Init(ILTCSBase *pInterface, const char* szAttributeFile="")
	{
		return Parse(pInterface, szAttributeFile);
	}

	bool Exist(const char* tag_name, const char* att_name = NULL)
	{
		static int nRecursionLevel = 0;

		if( !tag_name || strlen(tag_name) == 0 ) return false;

		if( ++nRecursionLevel > g_nMaxResursionLevel )
		{
			CString cstrErrorMessage;
			cstrErrorMessage.Format("Max recursion level reached for [%s]:%s.  Circular reference in Parent?",
				tag_name, att_name);
			GBM_DisplayError(cstrErrorMessage);

			--nRecursionLevel;
			return false;
		}

		if( m_buteMgr.Exist(tag_name,att_name) )
		{
			--nRecursionLevel;
			return true;
		}

		const CString parent_name = m_buteMgr.GetString(tag_name,"Parent",CString(""));
		if( stricmp(parent_name,tag_name)  == 0) 
		{
			--nRecursionLevel;
			return false;
		}

		const bool bResult = Exist( parent_name, att_name );

		--nRecursionLevel;
		return bResult;
	}

	int GetInt(const char * tag_name, const char * att_name, int def_value = 0)
	{
		static int nRecursionLevel = 0;

		if( !tag_name|| !att_name || strlen(tag_name) == 0 ) 
			return def_value;

		if( ++nRecursionLevel > g_nMaxResursionLevel )
		{
			CString cstrErrorMessage;
			cstrErrorMessage.Format("Max recursion level reached for [%s]:%s.  Circular reference in Parent?",
				tag_name, att_name);
			GBM_DisplayError(cstrErrorMessage);

			--nRecursionLevel;
			return def_value;
		}

		if( m_buteMgr.Exist(tag_name,att_name) )
		{
			--nRecursionLevel;
			return m_buteMgr.GetInt(tag_name,att_name);
		}

		const CString parent_name = m_buteMgr.GetString(tag_name,"Parent",CString(""));
		if( stricmp(parent_name,tag_name)  == 0) 
		{
			--nRecursionLevel;
			return def_value;
		}

		const int nResult = GetInt( parent_name, att_name, def_value );

		--nRecursionLevel;
		return nResult;
	}

	/* This requires that the number have an "f",  as in 1.0f.  If the "f"
	   is excluded the wrong number is read.  So I suggest not using it.

	DFLOAT GetFloat(const char * tag_name, const char * att_name, DFLOAT def_value = 0.0f )
	{
		if( !tag_name|| !att_name || strlen(tag_name) == 0 ) return def_value;

		if( m_buteMgr.Exist(tag_name,att_name) )
		{
			return m_buteMgr.GetFloat(tag_name,att_name);
		}

		return GetFloat( m_buteMgr.GetString(tag_name,"Parent",CString("")), att_name, def_value );
	}
	*/

	double GetDouble(const char * tag_name, const char * att_name, double def_value = 0.0 )
	{
		static int nRecursionLevel = 0;

		if( !tag_name|| !att_name || strlen(tag_name) == 0 ) 
			return def_value;

		if( ++nRecursionLevel > g_nMaxResursionLevel )
		{
			CString cstrErrorMessage;
			cstrErrorMessage.Format("Max recursion level reached for [%s]:%s.  Circular reference in Parent?",
				tag_name, att_name);
			GBM_DisplayError(cstrErrorMessage);

			--nRecursionLevel;
			return def_value;
		}

		if( m_buteMgr.Exist(tag_name,att_name) )
		{
			--nRecursionLevel;
			return m_buteMgr.GetDouble(tag_name,att_name);
		}

		const CString parent_name = m_buteMgr.GetString(tag_name,"Parent",CString(""));
		if( stricmp(parent_name,tag_name)  == 0) 
		{
			--nRecursionLevel;
			return def_value;
		}
		
		const double fResult = GetDouble( parent_name, att_name, def_value );
	
		--nRecursionLevel;
		return fResult;
	}


	CString GetString(const char * tag_name, const char * att_name, const CString & def_value = CString("") )
	{
	
		static int nRecursionLevel = 0;

		if( !tag_name|| !att_name || strlen(tag_name) == 0 ) 
			return def_value;

		if( ++nRecursionLevel > g_nMaxResursionLevel )
		{
			CString cstrErrorMessage;
			cstrErrorMessage.Format("Max recursion level reached for [%s]:%s.  Circular reference in Parent?",
				tag_name, att_name);
			GBM_DisplayError(cstrErrorMessage);

			--nRecursionLevel;
			return def_value;
		}

		if( m_buteMgr.Exist(tag_name,att_name) )
		{
			--nRecursionLevel;
			return m_buteMgr.GetString(tag_name,att_name);
		}

		const CString parent_name = m_buteMgr.GetString(tag_name,"Parent",CString(""));
		if( stricmp(parent_name,tag_name)  == 0) 
		{
			--nRecursionLevel;
			return def_value;
		}
		
		const CString cstrResult = GetString( parent_name, att_name, def_value );


		--nRecursionLevel;
		return cstrResult;
	}


	CPoint GetPoint(const char * tag_name, const char * att_name, const CPoint & def_value )
	{
		static int nRecursionLevel = 0;

		if( !tag_name|| !att_name || strlen(tag_name) == 0 ) 
			return def_value;

		if( ++nRecursionLevel > g_nMaxResursionLevel )
		{
			CString cstrErrorMessage;
			cstrErrorMessage.Format("Max recursion level reached for [%s]:%s.  Circular reference in Parent?",
				tag_name, att_name);
			GBM_DisplayError(cstrErrorMessage);

			--nRecursionLevel;
			return def_value;
		}

		if( m_buteMgr.Exist(tag_name,att_name) )
		{
			--nRecursionLevel;
			return m_buteMgr.GetPoint(tag_name,att_name);
		}

		const CString parent_name = m_buteMgr.GetString(tag_name,"Parent",CString(""));
		if( stricmp(parent_name,tag_name)  == 0) 
		{
			--nRecursionLevel;
			return def_value;
		}

		const CPoint ptResult = GetPoint( parent_name, att_name, def_value );

		--nRecursionLevel;
		return ptResult;
	}

	CPoint GetPoint(const char * tag_name, const char * att_name)
	{
		static CPoint def_value(0,0);
		return GetPoint(tag_name,att_name,def_value);
	}

	CAVector GetVector(const char * tag_name, const char * att_name, const CAVector & def_value )
	{
		static int nRecursionLevel = 0;

		if( !tag_name|| !att_name || strlen(tag_name) == 0 ) 
			return def_value;

		if( ++nRecursionLevel > g_nMaxResursionLevel )
		{
			CString cstrErrorMessage;
			cstrErrorMessage.Format("Max recursion level reached for [%s]:%s.  Circular reference in Parent?",
				tag_name, att_name);
			GBM_DisplayError(cstrErrorMessage);

			--nRecursionLevel;
			return def_value;
		}

		if( m_buteMgr.Exist(tag_name,att_name) )
		{
			--nRecursionLevel;
			return m_buteMgr.GetVector(tag_name,att_name);
		}

		const CString parent_name = m_buteMgr.GetString(tag_name,"Parent",CString(""));
		if( stricmp(parent_name,tag_name)  == 0) 
		{
			--nRecursionLevel;
			return def_value;
		}

		const CAVector caResult = GetVector( parent_name, att_name, def_value );

		--nRecursionLevel;
		return caResult;
	}

	CAVector GetVector(const char * tag_name, const char * att_name)
	{
		static CAVector def_value(0,0,0);
		return GetVector(tag_name,att_name,def_value);
	}

	CARange GetRange(const char * tag_name, const char * att_name, const CARange & def_value )
	{
		static int nRecursionLevel = 0;

		if( !tag_name|| !att_name || strlen(tag_name) == 0 ) 
			return def_value;

		if( ++nRecursionLevel > g_nMaxResursionLevel )
		{
			CString cstrErrorMessage;
			cstrErrorMessage.Format("Max recursion level reached for [%s]:%s.  Circular reference in Parent?",
				tag_name, att_name);
			GBM_DisplayError(cstrErrorMessage);

			--nRecursionLevel;
			return def_value;
		}

		if( m_buteMgr.Exist(tag_name,att_name) )
		{
			--nRecursionLevel;
			return m_buteMgr.GetRange(tag_name,att_name);
		}

		const CString parent_name = m_buteMgr.GetString(tag_name,"Parent",CString(""));
		if( stricmp(parent_name,tag_name)  == 0) 
		{
			--nRecursionLevel;
			return def_value;
		}

		const CARange rgResult = GetRange( parent_name, att_name, def_value );

		--nRecursionLevel;
		return rgResult;
	}

	CARange GetRange(const char * tag_name, const char * att_name)
	{
		static CARange def_value(0,0);
		return GetRange(tag_name,att_name,def_value);
	}

};

#endif //__HIERARCHICAL_BUTE_MGR_H__
