/*
 * 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_NS;
using namespace LOG4CXX_NS::pattern;
using namespace LOG4CXX_NS::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;
	int minDigitCount{ 0 }, maxDigitCount{ 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 = std::make_shared<FormattingInfo>(
									true, formattingInfo->getMinLength(),
									formattingInfo->getMaxLength());

						break;

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

						break;

					default:

						if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */))
						{
							formattingInfo = std::make_shared<FormattingInfo>(
										formattingInfo->isLeftAligned(), c - 0x30 /* '0' */,
										formattingInfo->getMaxLength());
							state = MIN_STATE;
							minDigitCount = 1;
						}
						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' */) && minDigitCount < 3)
				{
					formattingInfo = std::make_shared<FormattingInfo>(
								formattingInfo->isLeftAligned(),
								(formattingInfo->getMinLength() * 10) + (c - 0x30 /* '0' */),
								formattingInfo->getMaxLength());
					++minDigitCount;
				}
				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 = std::make_shared<FormattingInfo>(
								formattingInfo->isLeftAligned(), formattingInfo->getMinLength(),
								c - 0x30 /* '0' */);
					state = MAX_STATE;
					maxDigitCount = 1;
				}
				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' */) && maxDigitCount < 3)
				{
					formattingInfo = std::make_shared<FormattingInfo>(
								formattingInfo->isLeftAligned(), formattingInfo->getMinLength(),
								(formattingInfo->getMaxLength() * 10) + (c - 0x30 /* '0' */));
					++maxDigitCount;
				}
				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;
}
