/*
 * 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
{
	output.reserve(m_priv->expectedPatternLength + event->getMessage().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, event->getMessage());
	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 = event->getMessage();
	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)
				   );
}
