/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <log4cxx/logstring.h>
#include <log4cxx/pattern/patternparser.h>
#include <log4cxx/pattern/literalpatternconverter.h>
#include <log4cxx/helpers/loglog.h>

using namespace log4cxx;
using namespace log4cxx::pattern;
using namespace log4cxx::helpers;

const logchar PatternParser::ESCAPE_CHAR = 0x25; // '%'


/**
 * Private constructor.
 */
PatternParser::PatternParser()
{
}

bool PatternParser::isUnicodeIdentifierStart(logchar ch)
{
	//
	//   greatly simplified version checks if
	//     character is USACII alpha or number
	//
	return (ch >= 0x41 /* 'A' */ && ch <= 0x5A /* 'Z' */) ||
		(ch >= 0x61 /* 'a' */ && ch <= 0x7A /* 'z' */) ||
		(ch >= 0x30 /* '0' */ && ch <= 0x39 /* '9' */);
}

bool PatternParser::isUnicodeIdentifierPart(logchar ch)
{
	//
	//   greatly simplified version checks if
	//     character is USACII alpha or number
	//
	return isUnicodeIdentifierStart(ch)
		|| (ch == 0x5F /* '_' */);
}

int PatternParser::extractConverter(
	logchar lastChar, const LogString& pattern,
	LogString::size_type i, LogString& convBuf,
	LogString& currentLiteral)
{
	if (!convBuf.empty())
	{
		convBuf.erase(convBuf.begin(), convBuf.end());
	}

	// When this method is called, lastChar points to the first character of the
	// conversion word. For example:
	// For "%hello"     lastChar = 'h'
	// For "%-5hello"   lastChar = 'h'
	//System.out.println("lastchar is "+lastChar);
	if (!isUnicodeIdentifierStart(lastChar))
	{
		return i;
	}

	convBuf.append(1, lastChar);

	while (
		(i < pattern.length())
		&& isUnicodeIdentifierPart(pattern[i]))
	{
		convBuf.append(1, pattern[i]);
		currentLiteral.append(1, pattern[i]);

		//System.out.println("conv buffer is now ["+convBuf+"].");
		i++;
	}

	return i;
}


int PatternParser::extractOptions(const LogString& pattern, LogString::size_type i,
	std::vector<LogString>& options)
{
	while ((i < pattern.length()) && (pattern[i] == 0x7B /* '{' */))
	{
		int end = pattern.find(0x7D /* '}' */, i);

		if (end == -1)
		{
			break;
		}

		LogString r(pattern.substr(i + 1, end - i - 1));
		options.push_back(r);
		i = end + 1;
	}

	return i;
}

void PatternParser::parse(
	const LogString& pattern,
	std::vector<PatternConverterPtr>& patternConverters,
	std::vector<FormattingInfoPtr>& formattingInfos,
	const PatternMap& rules)
{

	LogString currentLiteral;

	int patternLength = pattern.length();
	int state = LITERAL_STATE;
	logchar c;
	int i = 0;
	FormattingInfoPtr formattingInfo(FormattingInfo::getDefault());

	while (i < patternLength)
	{
		c = pattern[i++];

		switch (state)
		{
			case LITERAL_STATE:

				// In literal state, the last char is always a literal.
				if (i == patternLength)
				{
					currentLiteral.append(1, c);

					continue;
				}

				if (c == ESCAPE_CHAR)
				{
					// peek at the next char.
					if (pattern[i] == ESCAPE_CHAR)
					{
						currentLiteral.append(1, c);
						i++; // move pointer
					}
					else
					{
						if (!currentLiteral.empty())
						{
							patternConverters.push_back(
								LiteralPatternConverter::newInstance(currentLiteral));
							formattingInfos.push_back(FormattingInfo::getDefault());
							currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
						}

						currentLiteral.append(1, c); // append %
						state = CONVERTER_STATE;
						formattingInfo = FormattingInfo::getDefault();
					}
				}
				else
				{
					currentLiteral.append(1, c);
				}

				break;

			case CONVERTER_STATE:
				currentLiteral.append(1, c);

				switch (c)
				{
					case 0x2D: // '-'
						formattingInfo =
							new FormattingInfo(
							true, formattingInfo->getMinLength(),
							formattingInfo->getMaxLength());

						break;

					case 0x2E: // '.'
						state = DOT_STATE;

						break;

					default:

						if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */))
						{
							formattingInfo =
								new FormattingInfo(
								formattingInfo->isLeftAligned(), c - 0x30 /* '0' */,
								formattingInfo->getMaxLength());
							state = MIN_STATE;
						}
						else
						{
							i = finalizeConverter(
									c, pattern, i, currentLiteral, formattingInfo,
									rules, patternConverters, formattingInfos);

							// Next pattern is assumed to be a literal.
							state = LITERAL_STATE;
							formattingInfo = FormattingInfo::getDefault();

							if (!currentLiteral.empty())
							{
								currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
							}
						}
				} // switch

				break;

			case MIN_STATE:
				currentLiteral.append(1, c);

				if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */))
				{
					formattingInfo =
						new FormattingInfo(
						formattingInfo->isLeftAligned(),
						(formattingInfo->getMinLength() * 10) + (c - 0x30 /* '0' */),
						formattingInfo->getMaxLength());
				}
				else if (c == 0x2E /* '.' */)
				{
					state = DOT_STATE;
				}
				else
				{
					i = finalizeConverter(
							c, pattern, i, currentLiteral, formattingInfo,
							rules, patternConverters, formattingInfos);
					state = LITERAL_STATE;
					formattingInfo = FormattingInfo::getDefault();

					if (!currentLiteral.empty())
					{
						currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
					}
				}

				break;

			case DOT_STATE:
				currentLiteral.append(1, c);

				if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */))
				{
					formattingInfo =
						new FormattingInfo(
						formattingInfo->isLeftAligned(), formattingInfo->getMinLength(),
						c - 0x30 /* '0' */);
					state = MAX_STATE;
				}
				else
				{
					LogLog::error(LOG4CXX_STR("Error in pattern, was expecting digit."));

					state = LITERAL_STATE;
				}

				break;

			case MAX_STATE:
				currentLiteral.append(1, c);

				if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */))
				{
					formattingInfo =
						new FormattingInfo(
						formattingInfo->isLeftAligned(), formattingInfo->getMinLength(),
						(formattingInfo->getMaxLength() * 10) + (c - 0x30 /* '0' */));
				}
				else
				{
					i = finalizeConverter(
							c, pattern, i, currentLiteral, formattingInfo,
							rules, patternConverters, formattingInfos);
					state = LITERAL_STATE;
					formattingInfo = FormattingInfo::getDefault();

					if (!currentLiteral.empty())
					{
						currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
					}
				}

				break;
		} // switch
	}

	// while
	if (currentLiteral.length() != 0)
	{
		patternConverters.push_back(
			LiteralPatternConverter::newInstance(currentLiteral));
		formattingInfos.push_back(FormattingInfo::getDefault());
	}
}


PatternConverterPtr PatternParser::createConverter(
	const LogString& converterId,
	LogString& currentLiteral,
	const PatternMap& rules,
	std::vector<LogString>& options)
{

	LogString converterName(converterId);

	for (int i = converterId.length(); i > 0; i--)
	{
		converterName = converterName.substr(0, i);
		PatternMap::const_iterator iter = rules.find(converterName);

		if (iter != rules.end())
		{
			currentLiteral.erase(currentLiteral.begin(),
				currentLiteral.end() - (converterId.length() - i));
			return (iter->second)(options);
		}
	}

	LogLog::error(LogString(LOG4CXX_STR("Unrecognized format specifier ")) + converterId);
	ObjectPtr converterObj;

	return converterObj;
}

int PatternParser::finalizeConverter(
	logchar c, const LogString& pattern, int i,
	LogString& currentLiteral, const FormattingInfoPtr& formattingInfo,
	const PatternMap&  rules,
	std::vector<PatternConverterPtr>& patternConverters,
	std::vector<FormattingInfoPtr>&  formattingInfos)
{
	LogString convBuf;
	i = extractConverter(c, pattern, i, convBuf, currentLiteral);

	if (convBuf.empty())
	{
		LogLog::error(LOG4CXX_STR("Empty conversion specifier"));
		patternConverters.push_back(
			LiteralPatternConverter::newInstance(currentLiteral));
		formattingInfos.push_back(FormattingInfo::getDefault());
	}
	else
	{
		LogString converterId(convBuf);

		std::vector<LogString> options;
		i = extractOptions(pattern, i, options);

		PatternConverterPtr pc(
			createConverter(
				converterId, currentLiteral, rules, options));

		if (pc == NULL)
		{
			LogString msg(LOG4CXX_STR("Unrecognized conversion specifier ["));
			msg.append(converterId);
			msg.append(LOG4CXX_STR("] in conversion pattern."));
			LogLog::error(msg);
			patternConverters.push_back(
				LiteralPatternConverter::newInstance(currentLiteral));
			formattingInfos.push_back(FormattingInfo::getDefault());
		}
		else
		{
			patternConverters.push_back(pc);
			formattingInfos.push_back(formattingInfo);

			if (currentLiteral.length() > 0)
			{
				patternConverters.push_back(
					LiteralPatternConverter::newInstance(currentLiteral));
				formattingInfos.push_back(FormattingInfo::getDefault());
			}
		}
	}

	if (!currentLiteral.empty())
	{
		currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
	}

	return i;
}
