#ifndef __LayerManager_h
#define __LayerManager_h

#include <map>	// For map template.

struct MC2LayerZOrder
{
	MC2LayerZOrder (DWORD dwA = DWORD(-1), DWORD dwB = DWORD(-1)) : dwLayerIdx(dwA), dwZOrder(dwB) {}
	DWORD	dwLayerIdx;
	DWORD	dwZOrder;
}; // struct MC2LayerZOrder.

inline bool operator < (const MC2LayerZOrder& a, const MC2LayerZOrder& b)
{
	if (a.dwLayerIdx < b.dwLayerIdx) return true;
	if (a.dwLayerIdx > b.dwLayerIdx) return false;
	if (a.dwZOrder < b.dwZOrder) return true;
	return false;
}

inline bool operator <= (const MC2LayerZOrder& a, const MC2LayerZOrder& b)
{
	if (a.dwLayerIdx < b.dwLayerIdx) return true;
	if (a.dwLayerIdx > b.dwLayerIdx) return false;
	if (a.dwZOrder <= b.dwZOrder) return true;
	return false;
}

inline bool operator == (const MC2LayerZOrder& a, const MC2LayerZOrder& b)
{
	if (a.dwLayerIdx == b.dwLayerIdx && a.dwZOrder == b.dwZOrder) return true;
	return false;
}

inline MC2LayerZOrder operator + (const MC2LayerZOrder& a, long l)
{
	return MC2LayerZOrder(a.dwLayerIdx, a.dwZOrder + l);
}

typedef map<const MC2ObjBase*, DWORD> MC2ObjectLZHashMap;

class MC2ZOrder;

class MC2LayerRec
{
public:
	MC2LayerRec (const wchar_t* tcpName, WORD wFlag, MC2ObjBaseVector* pvLayer);
	void	Delete ();
	wstring			m_strName;
	WORD			m_wFlag;
	MC2ObjBaseVector*	m_pvLayer;
}; // class MC2LayerRec.

typedef vector<MC2LayerRec>	MC2LayerRecVector;

/*************************************************************************
 * <_xZkqqHx_iDeOiDiJiDfI_xHqqkZx_>	MC2LayerManager
 *
 * <_xZkqqHx_iLeAjEfM_xHqqkZx_>	Document_xZkqqHx_iCmMjFjEjFgJiCmM_xHqqkZx_Z_xZkqqHx_iDeJiBfLiDfPiBfLiCpAiKmHjHjNiClHiCoJiDiMiDeDiDiEiBfLiDhNiDgMiBfLiDfHiDiDiDeOiDiJiDfIiBeC_xHqqkZx_
 *
 * <_xZkqqHx_jHjKjHpA_xHqqkZx_>	99.04.26 Fukushiro M. _xZkqqHx_iNoMjAkM_xHqqkZx_
 *************************************************************************/
class MC2LayerManager
{
public:
	MC2LayerManager (const wchar_t* tcpName, MC2ObjectLZHashMap& mpLZHash,
					MC2ObjBaseVector& vBottomLayer, MC2ObjBaseVector& vTopLayer);
	~MC2LayerManager ();
	void		DeleteAll ();
	const wchar_t*	GetName () const;
	void		SetName (const wchar_t* tcpName);
	void		OutStreamV3 (MCARCHIVE& ar) const;

	void		InsertLayer (DWORD dwLayerIdx, const wchar_t* tcpName, WORD wFlag);
	void		SetCurrentLayerIdx (DWORD dwIdx);
	void		AppendToLZOrder (MC2ObjBase* pObj);
	void		AppendToLZOrder (DWORD dwLayerIdx, MC2ObjBase* pObj);
	void		InsertToLZOrder (const MC2LayerZOrder& lzorder, MC2ObjBase* pObj);
	void		RemoveFromLZOrder (MC2ObjBase* pObj);
	MC2LayerZOrder	ObjBaseToLZOrder (const MC2ObjBase* pObj) const;
	MC2ObjBase*	LZOrderToObjBase (const MC2LayerZOrder& lzorder) const;

	DWORD		GetCurrentLayerIdx () const;
	void		GetZOrder (MC2ZOrder& zOrder, WORD wOption = FDOZ_ON_ANY, DWORD dwFromIdx = 0, DWORD dwUntilIdx = DWORD(-1)) const;
	DWORD			FirstLayerIdx (DWORD dwFromIdx, WORD wOption) const;
	DWORD			GetLayerSize () const;

protected:

	MC2ObjBaseVector*	GetObjOrder (DWORD dwLayerIdx) const;
	MC2ObjBaseVector*	GetTopObjOrder () const;
	BOOL		NextLZOrder (MC2LayerZOrder& lzorder) const;
	void		UpdateLZHashTable (const MC2LayerZOrder& lzorder);
	void		UpdateLZHashTable (MC2LayerZOrder lzorderFrom,
									MC2LayerZOrder lzorderUntil);
	void		EraseFromLZHashTable (const MC2ObjBase* pObj);

protected:
	wstring					m_strName;
	MC2ObjectLZHashMap*		m_mpLZHash;
	MC2LayerRecVector		m_vLayerTable;
	DWORD					m_dwCurLayerIdx;
}; // class MC2LayerManager.

#endif//__LayerManager_h

