#pragma once

#if 0

#if !defined(GENERICPARSER_H_INC)
#define GENERICPARSER_H_INC

#ifdef DEBUG_LINKING
	#pragma message("...including GenericParser.h")
#endif

#include "disablewarnings.h"

//
// CConfusedParser is a class designed to contain all of the functionality necessary for
//reading the text files containing CConfusedEntity information generated by ConfusED.
//
#pragma warning( push, 3 )

#if !defined(MAP_INC)
	#define MAP_INC
	#include <map>
#endif
#if !defined(STRING_INC)
	#define STRING_INC
	#include <string>
#endif
#if !defined(LIST_INC)
	#define LIST_INC
	#include <list>
#endif
#if !defined(VECTOR_INC)
	#define VECTOR_INC
	#include <vector>
#endif

#pragma warning( pop ) // stl sets warnings back on, so get mine back
using namespace std;

#include "disablewarnings.h"

class CParseGroup;

class CParseGroup
{
public:
	typedef	multimap<string, CParseGroup*>::iterator	TParseGroupIter;
	typedef	map<string, string>::iterator				TParsePairIter;

private:
	string								mName;
	map<string, string>					mPairs;
	multimap<string, CParseGroup*>		mSubGroups;
	CParseGroup*						mParent;
	vector<pair<string, string> >		mInOrderPairs;
	vector<pair<string, CParseGroup*> > mInOrderSubGroups;
	bool								mWriteable;

public:
	CParseGroup(bool writeable = false):
	mParent(NULL),
	mWriteable(writeable)
	{}
	CParseGroup(const string name, CParseGroup *parent, bool writeable = false):
	mName(name),
	mParent(parent),
	mWriteable(writeable)
	{}
	CParseGroup(CParseGroup *orig);

	~CParseGroup();

	CParseGroup		*GetParent()
	{ 
		return mParent;
	}
	string			GetName()
	{
		return mName; 
	}
	int				GetNumPairs() { return mPairs.size(); }
	int				GetNumSubGroups() { return mSubGroups.size(); }
	void			AddSubGroup(CParseGroup *grp) 
	{ 
		if (grp)
		{
			mSubGroups.insert(pair<string, CParseGroup*>(grp->GetName(),grp));
			if (mWriteable)
			{
				mInOrderSubGroups.push_back(pair<string, CParseGroup*>(grp->GetName(),grp));
			}
		}
	}
	void			AddPair(string key, string value)
	{ 
		mPairs[key] = value;
		if (mWriteable)
		{
			mInOrderPairs.push_back(pair<string, string>(key, value));
		}
	}
	void			AddPair(const char *key, const char *value)
	{ 
		mPairs[key] = value;
		if (mWriteable)
		{
			mInOrderPairs.push_back(pair<string, string>(key, value));
		}
	}
	void			SetPair(string key, string value)
	{
		mPairs[key] = value;
		if (mWriteable)
		{
			// try to find this pair in mInOrderPairs
			for (int i = 0; i < mInOrderPairs.size(); i++)
			{
				if (key.compare(mInOrderPairs[i].first) == 0)
				{
					mInOrderPairs[i].second = value;
					return;
				}
			}
			// doesn't exist yet so add a new pair
			mInOrderPairs.push_back(pair<string, string>(key, value));
		}
	}
	void			DeletePair(string key)
	{
		if (mWriteable)
		{
			map<string, string>::iterator it = mPairs.find(key);
			if (it != mPairs.end())
			{
				mPairs.erase(it);
			}

			// try to find this pair in mInOrderPairs
			for (vector<pair<string, string> >::iterator itInOrder = mInOrderPairs.begin(); itInOrder != mInOrderPairs.end(); ++itInOrder)
			{
				if (key.compare( (*itInOrder).first) == 0)
				{
					mInOrderPairs.erase(itInOrder);
					break;
				}
			}			
		}
	}
	string			FindPairValue(string key, string defaultVal);
	CParseGroup		*FindSubGroup(string name, bool recurse = false);
	CParseGroup		*FindSubGroupWithPair(string key, string value);
	bool			DeleteSubGroup(CParseGroup *delGroup);
	bool			WriteLine(int depth, const string line, string &output);
	bool			WriteGroup(string name, int depth, string &output);

	void			Clean();
	TParseGroupIter	GroupsBegin() {	return mSubGroups.begin(); }
	TParseGroupIter	GroupsEnd()	{ return mSubGroups.end(); }
	TParsePairIter	PairsBegin() { return mPairs.begin(); }
	TParsePairIter	PairsEnd() { return mPairs.end(); }
	// use these for writing (maintain the order in which the data was read)
	vector< pair<string, string> >		&GetInOrderPairs() { return mInOrderPairs; }
	vector< pair<string, CParseGroup*> > &GetInOrderGroups() { return mInOrderSubGroups; }
	void			SetWriteable(bool writeable) { mWriteable = writeable; }
};


class CGenericParser
{
private:
	string							mToken;
	int								mLineCount;
	const int						mMaxTokenLength;
	int								mBraceDepth;
	CParseGroup						*mCurGroup;
	CParseGroup						mGroups;
	bool							mWriteable;

protected:
	// really low level utility functions
	char		*SkipWhiteSpace( char *data, bool *newLine );
	string		&GetToken( char **dataPtr, const bool allowNewLines = true);
	void		EatCurrentLine( char **data );
	void		ReturnToBraceDepthZero(char **dataPtr);

	// higher level utility
	bool		ParseGroup(char **dataPtr);


public:
	CGenericParser();
	~CGenericParser();

	bool		Parse(char **dataPtr, bool cleanFirst = true, bool writeable = false);
	bool		Write(string &output);
	void		SetWriteable(bool writeable) { mWriteable = writeable; GetBaseParseGroup()->SetWriteable(writeable);}
	void		Clean() { mGroups.Clean(); }
	CParseGroup	*GetBaseParseGroup()
	{
		return &mGroups; 
	}
	CParseGroup *AddParseGroup(string groupName, CParseGroup &groupParent, bool writeable = true);
	bool DeleteParseGroup(CParseGroup *parentGroup, CParseGroup *delGroup);
};

#endif // GENERICPARSER_H_INC

#endif
