/****************************************************************************************************

		Id.h
		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	pascalc
		Date:	8/2/2005

****************************************************************************************************/

#ifndef __Id__
#define __Id__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCStream.h"
#include "MCToken.h"
#include "MCArray.h"
#include "MCPtrArray.h"
#include "MCClassArray.h"
#include "MCArrayTypes.h"
#include "MCHash.h"


//******************************************************************
	
// permanent Id class

class TId : public TMCObject
{
public:
	inline TId() { fId = 0; }
	inline TId(uint32 inId) { fId = inId; }
	inline boolean isValid() const { return fId != 0; }
	static inline TId Invalid() { return TId(); }
	inline void Write(TMCiostream& stream, int32 keyword) const { MCToken::PutUInt32Attribute(stream,keyword,fId); }
	static inline TId Read(TMCiostream& stream) { return TId( MCToken::GetUInt32Token(stream) ); }

	// shouldn't be used
	inline uint32 GetUint32() const { return fId; }
protected:
	uint32 fId;
};

class TTreeIdCounter;
class TTreeIdPath;

//******************************************************************

// permanent Tree Id
// there is a unique Id for each Tree in its Master Group

class TTreeId : public TId
{
friend class TTreeIdCounter;
friend class TTreeIdPath;
public:
	inline TTreeId(uint32 inId) : TId(inId) { }
	inline TTreeId() : TId() {}

	static inline TTreeId Invalid() { return TTreeId(); }
	static inline TTreeId Parent() { return TTreeId(kUInt32Minus1); }

	inline boolean isParent() const { return fId == -1; }

	inline boolean operator== (const TTreeId& otherId) const { return otherId.fId == fId; }
	inline boolean operator!= (const TTreeId& otherId) const { return otherId.fId != fId; }
	inline TTreeId& operator= (const TTreeId& otherId) { fId = otherId.fId; return *this; }
	static inline TTreeId Read(TMCiostream& stream) { return TTreeId( MCToken::GetUInt32Token(stream) ); }
		
};


MCDEFINE_GUID_H(IID_I3DTreeIdUser);

struct I3DTreeIdUser : public IMCUnknown
{
	virtual void	MCCOMAPI RenamedTreePermanentID(const TMCHashMap<TTreeId, TTreeId>& renamedTreeId) = 0;
};

//******************************************************************

// permanent Id Counter

class TTreeIdCounter : public TMCObject
{
public:
	inline TTreeIdCounter() { lastId = 1; }
	inline TTreeId GetNext() { return TTreeId(lastId++); }
	inline void Register(TTreeId inId) { if (lastId <= inId.fId) lastId = inId.fId+1; }
protected:
	uint32 lastId;
};

//******************************************************************

// tree id path : list of permanent Ids

class TTreeIdPath : public TMCObject
{
public:
	inline TTreeIdPath() { }
	inline static TTreeIdPath Root() { return TTreeIdPath(); }
	inline static TTreeIdPath InvalidPath() { return TTreeIdPath() + TTreeId::Invalid(); }
	boolean isValid() const { return path.GetElemCount() == 0 || path[0].isValid(); }
	boolean isRoot() const { return path.GetElemCount() == 0; }

	inline uint32 Length() const{ return path.GetElemCount(); }

	boolean operator == (const TTreeIdPath& otherPath) const;
	inline boolean operator != (const TTreeIdPath& otherPath) const { return !operator==(otherPath); }
	boolean operator> (const TTreeIdPath& insideAbsolute) const;
	inline TTreeIdPath& operator+= (const TTreeId& son) { path.AddElem(son); return *this; }
	inline TTreeIdPath& operator-- () { path.RemoveElem(path.GetElemCount()-1, 1); return *this; }
	inline TTreeIdPath& operator= (const TTreeIdPath& fromPath) { path = fromPath.path; return *this; }

	boolean		IsSubPath(const TTreeIdPath& root) const;
	void		RenamedTreePermanentID(const TMCHashMap<TTreeId, TTreeId>& renamedTreeId);

	friend	TTreeIdPath operator+ (const TTreeIdPath& parentAbsolute, const TTreeId& son);

	TTreeIdPath makeRelativeTo (const TTreeIdPath& parentAbsolute) const;
	TTreeIdPath makeAbsoluteFrom (const TTreeIdPath& parentAbsolute) const;
	inline TTreeId First() const { return path[0]; }
	inline TTreeIdPath Next() const { TTreeIdPath out = *this; out.path.RemoveElem(0,1); return out; }

	static TTreeIdPath Read(TMCiostream& stream);
	void Write(TMCiostream& stream, int32 keyword) const;

protected:
	TMCArray<TTreeId> path;
};


//******************************************************************

// tree id path : list of permanent Ids

class TTreeIdPathList : public TMCClassArray<TTreeIdPath>
{
public:
	TTreeIdPathList();
	~TTreeIdPathList();

	void DeleteAllPaths			();
	void CopyDataFrom			(const TTreeIdPathList& fromList);
};


//******************************************************************

// tree id referencer : a class that references trees by id

MCDEFINE_GUID_H(IID_ITreeIDReferencer);

typedef I3DShTreeElement* TTreeElementReference;

struct ITreeIDReferencer : public IMCUnknown
{
	virtual void	MCCOMAPI ReferencesChanged(const TMCHashMap<TTreeId, I3DShTreeElement*>& renamedTreeId) = 0;
};

#endif
