#include "pptable.h"
#include <wx/tokenzr.h>
#include <set>

bool IsWordChar(const wxString &s, int strSize)
{
	if(strSize) {
		return s.find_first_of(wxT("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_")) != wxString::npos;

	} else {
		return s.find_first_of(wxT("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_")) != wxString::npos;
	}
}

bool IsWordCharA(char c, int strSize)
{
	if(strSize) {
		return ((c >= 97 && c <= 122) ||// a-z
				(c >= 65 && c <= 90)  ||// A-Z
				(c >= 48 && c <= 57)  ||// 0-9
				(c == '_'));

	} else {
		return ((c >= 97 && c <= 122) ||// a-z
				(c >= 65 && c <= 90)  ||// A-Z
				(c == '_'));
	}
}

std::string ReplaceWordA(const std::string &str, const std::string &word, const std::string &replaceWith)
{
	char        currChar;
	char        nextChar;
	std::string currentWord;
	std::string output;

	output.reserve( str.length() * 2 );

	for(size_t i=0; i<str.length(); i++) {
		// Look ahead
		if( str.length() > i + 1 ) {
			nextChar = str[i+1];
		} else {
			// we are at the end of buffer
			nextChar = '\0';
		}

		currChar = str[i];
		if(!IsWordCharA( currChar, currentWord.length() )) {
			output += str[i];
			currentWord.clear();

		} else {

			currentWord += currChar;
			if(IsWordCharA(nextChar, currentWord.length())) {
				// do nothing

			} else if( !IsWordCharA(nextChar, currentWord.length()) && currentWord == word ) {
				output += replaceWith;
				currentWord.clear();

			} else {
				output += currentWord;
				currentWord.clear();
			}

		}
	}
	return output;
}

// Helper string find metho
wxString ReplaceWord(const wxString &str, const wxString &word, const wxString &replaceWith)
{
	wxString currChar;
	wxString nextChar;
	wxString currentWord;
	wxString output;
	for(size_t i=0; i<str.Length(); i++) {
		// Look ahead
		if( str.Length() > i + 1 ) {
			nextChar = str[i+1];
		} else {
			// we are at the end of buffer
			nextChar = wxT('\0');
		}

		currChar = str[i];
		if(!IsWordChar( currChar, currentWord.Length() )) {
			output << str[i];
			currentWord.Clear();

		} else {

			currentWord << currChar;
			if(IsWordChar(nextChar, currentWord.Length())) {
				// do nothing

			} else if( !IsWordChar(nextChar, currentWord.Length()) && currentWord == word ) {
				output << replaceWith;
				currentWord.Clear();

			} else {
				output << currentWord;
				currentWord.Clear();
			}

		}
	}
	return output;
}

wxArrayString TokenizeWords(const wxString &str)
{
	wxString currChar;
	wxString nextChar;
	wxString currentWord;
	wxArrayString outputArr;
	
	wxString::const_iterator iter = str.begin();
	for(; iter != str.end(); iter++) {
		// Look ahead
		if( (iter + 1) != str.end() ) {
			 nextChar = *(iter+1);
		} else {
			// we are at the end of buffer
			nextChar = wxT('\0');
		}

		currChar = *iter;
		if(!IsWordChar( currChar, currentWord.Length() )) {
			currentWord.Clear();

		} else {

			currentWord << currChar;
			if(IsWordChar(nextChar, currentWord.Length())) {
				// do nothing

			} else {

				outputArr.Add(currentWord);
				currentWord.Clear();
			}

		}
	}
	return outputArr;
}

static PPTable* ms_instance = NULL;
	
void PPToken::processArgs(const wxString &argsList)
{
	args = wxStringTokenize(argsList, wxT(","), wxTOKEN_STRTOK);

	// replace all occurrences of 'arg' with %1, %2 etc
	for(size_t i=0; i<args.GetCount(); i++) {
		wxString replaceWith = wxString::Format(wxT("%%%d"), (int)i);
#if wxVERSION_NUMBER < 2900
		replacement = ReplaceWord(replacement, args.Item(i), replaceWith);
#else
		std::string res = ReplaceWordA(replacement.To8BitData().data(), args.Item(i).To8BitData().data(), replaceWith.To8BitData().data());
		if(res.empty()) {
			replacement.clear();
			
		} else {
			replacement = wxString::From8BitData(res.c_str());
			
		}
#endif
	}
}

void PPToken::print(wxFFile &fp)
{
#if 0
	wxString buff;
	buff << wxT("Name          : ") << name << wxT("\n");
	buff << wxT("replacement   : ") << replacement << wxT("\n");
	buff << wxT("isFunctionLike: ") << isFunctionLike << wxT("\n");
	if(isFunctionLike) {
		for(size_t i=0; i<args.size(); i++) {
			buff << wxT("Arg: ") << args.Item(i) << wxT("\n");
		}
	}
	buff << wxT(" ---- \n");
	fp.Write(buff);
#else
	wxString buff;
	buff << name << wxT("(") << (flags & IsFunctionLike) << wxT(")") << wxT("=") << replacement << wxT("\n");
	fp.Write(buff);
#endif
}

wxString PPToken::fullname() const
{
	wxString fullname;
	fullname << name;
	if(flags & IsFunctionLike) {
		fullname << wxT("(");
		for(size_t i=0; i<args.size(); i++) {
			fullname << wxT("%") << i << wxT(",");
		}
		if(args.size()) {
			fullname.RemoveLast();
		}
		fullname << wxT(")");
	}
	return fullname;
}

void PPToken::squeeze()
{
	std::set<wxString> alreadyReplacedMacros;

	// perform the squeeze 5 times max
	for(size_t count=0; count < 5; count++) {
		bool modified(false);

		// get list of possible macros in the replacement
		wxArrayString tmpWords = TokenizeWords(replacement);
		wxArrayString words;

		// make sure that a word is not been replaced more than once
		// this will avoid recursion
		// an example (taken from qglobal.h of the Qt library):
		//
		// #define qDebug QT_NO_QDEBUG_MACRO
		// #define QT_NO_QDEBUG_MACRO if(1); else qDebug
		//
		for(size_t i=0; i<tmpWords.size(); i++) {
			if(alreadyReplacedMacros.find(tmpWords.Item(i)) == alreadyReplacedMacros.end()){
				alreadyReplacedMacros.insert(tmpWords[i]);
				words.Add(tmpWords[i]);
			}
		}

		for(size_t i=0; i<words.size(); i++) {
			PPToken tok = PPTable::Instance()->Token(words.Item(i));
			if(tok.flags & IsValid) {
				if(tok.flags & IsFunctionLike) {
					int where = replacement.Find(words.Item(i));
					if(where != wxNOT_FOUND) {
						wxString      initList;
						wxArrayString initListArr;
						if(readInitList( replacement, where + words.Item(i).Length(), initList, initListArr )) {
							tok.expandOnce(initListArr);

							replacement.Remove(where, words.Item(i).Length() + initList.Length());
							tok.replacement.Replace(wxT("##"), wxT(""));
							replacement.insert(where, tok.replacement);
							modified = true;
						}
					}

				} else {
					if(replacement.Replace(words.Item(i), tok.replacement)) {
						modified = true;
					}
				}
			}
		}

		if(!modified)
			break;
	}
	replacement.Replace(wxT("##"), wxT(""));
}

bool PPToken::readInitList(const std::string& in, size_t from, std::string& initList, std::vector<std::string>& initListArr)
{
	if(in.length() < from) {
		return false;
	}

	std::string tmpString = in.substr(from);
	size_t      start     = tmpString.find('(');
	if(start == std::string::npos ) {
		return false;
	}

	// skip the open brace
	tmpString = tmpString.substr(start+1);

	for(size_t i=0; i<start; i++) {
		initList += " ";
	}

	initList += "(";
	std::string word;
	int depth(1);

	for(size_t i=0; i<tmpString.length(); i++) {
		char ch = tmpString[i];
		initList += ch;
		switch(ch) {
		case ')':
			depth --;
			if(depth == 0) {
				initListArr.push_back(word);
				return true;
			} else {
				word += ch;
			}
			break;
		case '(':
			depth++;
			word += ch;
			break;
		case ',':
			if(depth == 1) {
				initListArr.push_back(word);
				word.clear();
			} else {
				word += ch;
			}
			break;
		default:
			word += ch;
			break;
		}
	}
	return false;
}

bool PPToken::readInitList(const wxString &in, int from, wxString& initList, wxArrayString& initListArr)
{
	if((int)in.Length() < from) {
		return false;
	}

	wxString tmpString = in.Mid(from);
	int start = tmpString.Find(wxT("("));
	if(start == wxNOT_FOUND ) {
		return false;
	}
	tmpString = tmpString.Mid(start+1);

	for(size_t i=0; i<(size_t)start; i++) {
		initList << wxT(" ");
	}

	initList << wxT("(");
	wxString word;
	int depth(1);

	for(size_t i=0; i<tmpString.Length(); i++) {
		wxChar ch = tmpString[i];
		initList << ch;
		switch(ch) {
		case wxT(')'):
			depth --;
			if(depth == 0) {
				initListArr.Add(word);
				return true;
			} else {
				word << ch;
			}
			break;
		case wxT('('):
			depth++;
			word << ch;
			break;
		case wxT(','):
			if(depth == 1) {
				initListArr.Add(word);
				word.Clear();
			} else {
				word << ch;
			}
			break;
		default:
			word << ch;
			break;
		}
	}
	return false;
}

void PPToken::expandOnce(const wxArrayString& initList)
{
	if(initList.size() != args.size())
		return;

	for(size_t i=0; i<args.size(); i++) {
		wxString placeHolder;
		placeHolder << wxT("%") << i;
		
		wxString replaceWith = initList.Item(i);
		replaceWith.Trim().Trim(false);
		
		if(replaceWith.Contains(placeHolder))
			continue;
		
		replacement.Replace(placeHolder, initList.Item(i));
	}
}

wxString PPToken::signature() const
{
	wxString sig;
	if(flags & IsFunctionLike) {
		sig << wxT("(");
		for(size_t i=0; i<args.size(); i++) {
			sig << wxT("%") << i << wxT(",");
		}
		if(args.size()) {
			sig.RemoveLast();
		}
		sig << wxT(")");
	}
	return sig;
}

///////////////////////////////////////////////////

PPTable::PPTable()
{
}

PPTable::~PPTable()
{
}

PPTable* PPTable::Instance()
{
	if(ms_instance == NULL) {
		ms_instance = new PPTable();
	}
	return ms_instance;
}

void PPTable::Release()
{
	if(ms_instance) {
		delete ms_instance;
	}
	ms_instance = NULL;
}

PPToken PPTable::Token(const wxString& name)
{
	std::map<wxString, PPToken>::iterator iter = m_table.find(name);
	if(iter == m_table.end()) {
		return PPToken();
	}

	return iter->second;
}

void PPTable::Add(const PPToken& token)
{
	if(token.name.IsEmpty())
		return;

	wxString name = token.name;
	name.Trim().Trim(false);
	std::map<wxString, PPToken>::iterator iter = m_table.find(name);
	if(iter == m_table.end())
		m_table[name] = token;
	else {
		// if the new token's replacement is empty and the current one is NOT empty,
		// replace the two (we prefer empty replacements)
		if(iter->second.flags & PPToken::IsOverridable && !iter->second.replacement.IsEmpty() && token.replacement.IsEmpty()) {
			m_table[name] = token;
		}
	}
}

void PPTable::AddUsed(const wxString& name)
{
	if(name.IsEmpty()) {
		return;
	}
	m_namesUsed.insert(name);
}

void PPTable::Print(wxFFile &fp)
{
	std::map<wxString, PPToken>::iterator iter = m_table.begin();
	for(; iter != m_table.end(); iter++) {
		iter->second.print(fp);
	}
}

bool PPTable::Contains(const wxString& name)
{
	std::map<wxString, PPToken>::iterator iter = m_table.find(name);
	return iter != m_table.end();
}

wxString PPTable::Export()
{
	wxString table;
	std::map<wxString, PPToken>::iterator iter = m_table.begin();
	for(; iter != m_table.end(); iter++) {
		iter->second.squeeze();
		wxString replacement = iter->second.replacement;
		replacement.Trim().Trim(false);
		
		// remove extra whitespaces
		while(replacement.Replace(wxT("  "), wxT(" "))){}
		
		if(replacement.IsEmpty()) {
			table << iter->second.fullname() << wxT("\n");

		} else if(iter->second.flags & PPToken::IsFunctionLike) {
			table << iter->second.fullname() << wxT("=") << replacement << wxT("\n");

		} else {
			// macros with replacement but they are not in a form of a function
			// we take only macros that their replacement is not a number
			long v(-1);
			if(!replacement.ToLong(&v) && !replacement.ToLong(&v, 8) && !replacement.ToLong(&v, 16) && replacement.find(wxT('"')) == wxString::npos && !replacement.StartsWith(wxT("0x"))) {
				table << iter->second.fullname() << wxT("=") << replacement << wxT("\n");
			}
		}
	}
	return table;
}

void PPTable::Squeeze()
{
	std::map<wxString, PPToken>::iterator iter = m_table.begin();
	for(; iter != m_table.end(); iter++) {
		m_table[iter->first].squeeze();
	}
}

void PPTable::Clear()
{
	m_table.clear();
}

void PPTable::ClearNamesUsed()
{
	m_namesUsed.clear();
}

bool CLReplacePattern(const wxString& in, const wxString& pattern, const wxString& replaceWith, wxString &outStr)
{
	int where = pattern.Find(wxT("%0"));
	if(where != wxNOT_FOUND) {
		wxString replacement(replaceWith);

		// a patterened expression
		wxString searchFor = pattern.BeforeFirst(wxT('('));
		where = in.Find(searchFor);
		if(where == wxNOT_FOUND) {
			return false;
		}

		wxString      initList;
		wxArrayString initListArr;
		if(PPToken::readInitList(in, searchFor.Length() + where, initList, initListArr) == false)
			return false;

		outStr = in;
		// update the 'replacement' with the actual values ( replace %0..%n)
		for(size_t i=0; i<initListArr.size(); i++) {
			wxString placeHolder;
			placeHolder << wxT("%") << i;
			replacement.Replace(placeHolder, initListArr.Item(i));
		}

		outStr.Remove(where, searchFor.Length() + initList.Length());
		outStr.insert(where, replacement);
		return true;

	} else {
		if(in.Find(pattern) == wxNOT_FOUND) {
			return false;
		}
		// simple replacement
		outStr = ReplaceWord(in, pattern, replaceWith);
		return outStr != in;
	}
}

std::string replacement;

bool CLReplacePatternA(const std::string& in, const CLReplacement& repl, std::string& outStr)
{
	if(repl.is_compound) {
		size_t where = in.find(repl.searchFor);
		if(where == std::string::npos)
			return false;

		std::string              initList;
		std::vector<std::string> initListArr;
		if(PPToken::readInitList(in, repl.searchFor.length() + where, initList, initListArr) == false)
			return false;

		// update the 'replacement' with the actual values ( replace %0..%n)
		replacement = repl.replaceWith;
		char placeHolder[4];
		for(size_t i=0; i<initListArr.size(); i++) {

            memset(placeHolder, 0, sizeof(placeHolder));
            sprintf(placeHolder, "%%%d", (int)i);

			size_t pos = replacement.find(placeHolder);
			const std::string& init = initListArr[i];
            while( pos != std::string::npos ) {
				replacement.replace(pos, strlen(placeHolder), init.c_str());

				// search for the next match
                pos = replacement.find(placeHolder, pos + 1);
            }
		}

		outStr = in;
		where = outStr.find(repl.searchFor);
		if(where == std::string::npos)
			return false;

		outStr.replace(where, repl.searchFor.length() + initList.length(), replacement);
		return true;

	} else {

		size_t where = in.find(repl.searchFor);
		if(where == std::string::npos) {
			return false;
		}

		outStr = ReplaceWordA(in, repl.searchFor, repl.replaceWith);

//		outStr = in;
//		outStr.replace(where, repl.searchFor.length(), repl.replaceWith);

		// simple replacement
		return outStr != in;
	}
}

void CLReplacement::construct(const std::string& pattern, const std::string& replacement)
{
	is_ok = true;
	full_pattern = pattern;
	is_compound  = full_pattern.find("%0") != std::string::npos;
	if(is_compound) {
		// a patterened expression
		replaceWith = replacement;
		size_t where = pattern.find('(');
		if(where == std::string::npos) {
			is_ok = false;
			return;
		}

		searchFor = pattern.substr(0, where);
		if(searchFor.empty()){
			is_ok = false;
			return;
		}

	} else {
		// simple Key=Value pair
		replaceWith = replacement;
		searchFor   = full_pattern;
	}
}

