/*
 * 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 /* '_' */);
}

size_t 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;
}


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

		if (end == pattern.npos)
		{
			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;

	size_t patternLength = pattern.length();
	int state = LITERAL_STATE;
	logchar c;
	size_t 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 = FormattingInfoPtr(
								new FormattingInfo(
									true, formattingInfo->getMinLength(),
									formattingInfo->getMaxLength()));

						break;

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

						break;

					default:

						if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */))
						{
							formattingInfo = FormattingInfoPtr(
									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 = FormattingInfoPtr(
							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 = FormattingInfoPtr(
							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 = FormattingInfoPtr(
							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 (size_t 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);

	return PatternConverterPtr();
}

size_t PatternParser::finalizeConverter(
	logchar c, const LogString& pattern, size_t 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;
}
