/*
 * 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/fmtlayout.h>
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/level.h>
#include <chrono>

#include <fmt/format.h>
#include <fmt/chrono.h>

using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::spi;

struct FMTLayout::FMTLayoutPrivate{
	FMTLayoutPrivate()
		: expectedPatternLength(100)
		{}

	FMTLayoutPrivate(const LogString& pattern)
		: conversionPattern(pattern)
		, expectedPatternLength(100)
	{}

	LogString conversionPattern;

	// Expected length of a formatted event excluding the message text
	size_t expectedPatternLength;
};

IMPLEMENT_LOG4CXX_OBJECT(FMTLayout)

FMTLayout::FMTLayout() :
	m_priv(std::make_unique<FMTLayoutPrivate>())
{}

FMTLayout::FMTLayout(const LogString& pattern) :
	m_priv(std::make_unique<FMTLayoutPrivate>(pattern))
{}

FMTLayout::~FMTLayout(){}

void FMTLayout::setConversionPattern(const LogString& pattern)
{
	m_priv->conversionPattern = pattern;
	helpers::Pool pool;
	activateOptions(pool);
}

LogString FMTLayout::getConversionPattern() const
{
	return m_priv->conversionPattern;
}

void FMTLayout::setOption(const LogString& option, const LogString& value)
{
	if (helpers::StringHelper::equalsIgnoreCase(option,
			LOG4CXX_STR("CONVERSIONPATTERN"),
			LOG4CXX_STR("conversionpattern")))
	{
		m_priv->conversionPattern = helpers::OptionConverter::convertSpecialChars(value);
	}
}

void FMTLayout::activateOptions(helpers::Pool&)
{
	m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
}

void FMTLayout::format(LogString& output,
	const spi::LoggingEventPtr& event,
	LOG4CXX_NS::helpers::Pool&) const
{
	auto& lsMsg = event->getRenderedMessage();
	output.reserve(m_priv->expectedPatternLength + lsMsg.size());
	auto locationFull = fmt::format("{}({})",
										 event->getLocationInformation().getFileName(),
										 event->getLocationInformation().getLineNumber());
	LogString ndc;
	event->getNDC(ndc);
#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_LOGCHAR_IS_UNICHAR
	LOG4CXX_ENCODE_CHAR(sNDC, ndc);
	LOG4CXX_ENCODE_CHAR(sPattern, m_priv->conversionPattern);
	LOG4CXX_ENCODE_CHAR(sLogger, event->getLoggerName());
	LOG4CXX_ENCODE_CHAR(sLevel, event->getLevel()->toString());
	LOG4CXX_ENCODE_CHAR(sMsg, lsMsg);
	LOG4CXX_ENCODE_CHAR(sThread, event->getThreadName());
	LOG4CXX_ENCODE_CHAR(endOfLine, LOG4CXX_EOL);
#else
	auto& sNDC = ndc;
	auto& sPattern = m_priv->conversionPattern;
	auto& sLogger = event->getLoggerName();
	auto sLevel = event->getLevel()->toString();
	auto& sMsg = lsMsg;
	auto& sThread = event->getThreadName();
	auto endOfLine = LOG4CXX_EOL;
#endif
	fmt::format_to(std::back_inserter(output),
				   fmt::runtime(sPattern),
				   fmt::arg("d", event->getChronoTimeStamp()),
				   fmt::arg("c", sLogger),
				   fmt::arg("logger", sLogger),
				   fmt::arg("f", event->getLocationInformation().getShortFileName()),
				   fmt::arg("shortfilename", event->getLocationInformation().getShortFileName()),
				   fmt::arg("F", event->getLocationInformation().getFileName()),
				   fmt::arg("filename", event->getLocationInformation().getFileName()),
				   fmt::arg("l", locationFull),
				   fmt::arg("location", locationFull),
				   fmt::arg("L", event->getLocationInformation().getLineNumber()),
				   fmt::arg("line", event->getLocationInformation().getLineNumber()),
				   fmt::arg("m", sMsg),
				   fmt::arg("message", sMsg),
				   fmt::arg("M", event->getLocationInformation().getMethodName()),
				   fmt::arg("method", event->getLocationInformation().getMethodName()),
				   fmt::arg("n", endOfLine),
				   fmt::arg("newline", endOfLine),
				   fmt::arg("p", sLevel),
				   fmt::arg("level", sLevel),
				   fmt::arg("r", event->getTimeStamp()),
				   fmt::arg("t", sThread),
				   fmt::arg("thread", sThread),
				   fmt::arg("T", sThread),
				   fmt::arg("threadname", sThread),
				   fmt::arg("x", sNDC),
				   fmt::arg("ndc", sNDC)
				   );
}
