#pragma once

class ObjectNameList;
class ObjectNameList__Entry;
class NameList;
class AlphaNameList;

class ObjectNameList SIGNATURED
{
public:
	typedef ObjectNameList__Entry Entry;

protected:
	Entry *firstEntry, *lastEntry;

public:
	ObjectNameList();
	virtual ~ObjectNameList();

	virtual const char* AddEntry(const char *name, void *data);
	void* FindObject(const char *name);
	void DeleteEntry(const char *name);
	int EntryCount() const;
	Logical IsEmpty() const
	{
		Check(this);
		return firstEntry == NULL && lastEntry == NULL;
	}
	Entry* GetFirstEntry()
	{
		Check(this);
		return firstEntry;
	}
	const Entry* GetFirstEntry() const
	{
		Check(this);
		return firstEntry;
	}
	Entry* GetLastEntry()
	{
		Check(this);
		return lastEntry;
	}
	const Entry* GetLastEntry() const
	{
		Check(this);
		return lastEntry;
	}
	int BuildSubList(const ObjectNameList &source_list, const char *prefix);

	Logical TestInstance() const;
	static Logical TestClass();
};

class ObjectNameList__Entry
{
	friend class ObjectNameList;
	friend class NameList;
	friend class AlphaNameList;

private:
	ObjectNameList::Entry *nextEntry;

public:
	void *dataReference;

protected:
	void SetName(const char *name);

public:
	#if defined(USE_SIGNATURE)
		friend int Is_Signature_Bad(const volatile ObjectNameList__Entry *);
	#endif

	const char* GetName() const
	{
		Check(this);
		return &((const char *)this)[sizeof(ObjectNameList::Entry)];
	}
	Logical IsName(const char *name) const;

	/*
	 *	HACK SB 01/21/07	-- Windows uses this function name and macros it,
								and GetData seems to do the same thing, so don't
								use this.
	void* GetObject()
	{
		Check(this);
		return dataReference;
	}
	*/
	void* GetData()
	{
		Check(this);
		return dataReference;
	}
	const void* GetData() const
	{
		Check(this);
		return dataReference;
	}
	char* GetChar()
	{
		Check(this);
		return (char *)dataReference;
	}
	const char* GetChar() const
	{
		Check(this);
		return (const char *)dataReference;
	}
	int GetAtoi() const
	{
		Check(this);
		Check_Pointer(dataReference);
		return atoi((const char *)dataReference);
	}
	long GetAtol() const
	{
		Check(this);
		Check_Pointer(dataReference);
		return atol((const char *)dataReference);
	}
	double GetAtof() const
	{
		Check(this);
		Check_Pointer(dataReference);
		return atof((const char *)dataReference);
	}
	ObjectNameList::Entry* GetNextEntry()
	{
		Check(this);
		return nextEntry;
	}
	const ObjectNameList::Entry* GetNextEntry() const
	{ 
		Check(this);
		return nextEntry;
	}
	Logical TestInstance() const;
};

class NameList : public ObjectNameList
{
public:
	NameList();
	~NameList();

	void* FindData(const char *name)	{ return FindObject(name); }
	const char* FindName(void *data);
	Entry* FindEntry(const char *name);
	Entry* FindEntry(void *data);
	void DeleteEntry(const char *name);	// this one is searches for name
	static Logical TestClass();
};

class AlphaNameList : public NameList
{
public:
	AlphaNameList();
	~AlphaNameList();

	const char* AddEntry(const char *name, void *data);
	static Logical TestClass();
};