#include <log4cxx/logger.h>
#include <log4cxx/patternlayout.h>
#include <log4cxx/appenderskeleton.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/asyncappender.h>
#if LOG4CXX_USING_STD_FORMAT
#include <format>
#else
#include <fmt/format.h>
#endif
#include <benchmark/benchmark.h>
#include <thread>
#include <cstdlib>
#include <iomanip>

using namespace log4cxx;

class NullWriterAppender : public AppenderSkeleton
{
public:
	DECLARE_LOG4CXX_OBJECT(NullWriterAppender)
	BEGIN_LOG4CXX_CAST_MAP()
	LOG4CXX_CAST_ENTRY(NullWriterAppender)
	LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
	END_LOG4CXX_CAST_MAP()

	NullWriterAppender() {}

	void close() override {}

	bool requiresLayout() const override
	{
		return true;
	}

	void append(const spi::LoggingEventPtr& event, helpers::Pool& p) override
	{
		// This gets called whenever there is a valid event for our appender.
	}

	void activateOptions(helpers::Pool& /* pool */) override
	{
		// Given all of our options, do something useful(e.g. open a file)
	}

	void setOption(const LogString& option, const LogString& value) override
	{
	}
};

IMPLEMENT_LOG4CXX_OBJECT(NullWriterAppender)

#if defined(LOG4CXX_VERSION_MINOR) && (0 < LOG4CXX_VERSION_MAJOR || 11 < LOG4CXX_VERSION_MINOR)
LOG4CXX_PTR_DEF(NullWriterAppender);
#else
#define LOG4CXX_HAS_FMT 0
template class log4cxx::helpers::ObjectPtrT<NullWriterAppender>;
typedef log4cxx::helpers::ObjectPtrT<NullWriterAppender> NullWriterAppenderPtr;
#endif

class benchmarker : public ::benchmark::Fixture
{
public:
	LoggerPtr m_logger;
	void SetupLogger()
	{
		m_logger = Logger::getLogger(LOG4CXX_STR("bench_logger"));

		m_logger->removeAllAppenders();
		m_logger->setAdditivity(false);
		m_logger->setLevel(Level::getInfo());

		PatternLayoutPtr pattern(new PatternLayout);
		pattern->setConversionPattern(LOG4CXX_STR("%m%n"));

		NullWriterAppenderPtr nullWriter(new NullWriterAppender);
		nullWriter->setName(LOG4CXX_STR("NullWriterAppender"));
		nullWriter->setLayout(pattern);

		m_logger->addAppender(nullWriter);
	}

	void SetUp(const ::benchmark::State& state)
	{
		std::setlocale( LC_ALL, "" ); /* Set locale for C functions */
		std::locale::global(std::locale("")); /* set locale for C++ functions */
		SetupLogger();
	}

	void TearDown(const ::benchmark::State& state)
	{
	}

	static int threadCount()
	{
		auto threadCount = helpers::StringHelper::toInt
			(helpers::OptionConverter::getSystemProperty
				(LOG4CXX_STR("LOG4CXX_BENCHMARK_THREAD_COUNT"), LOG4CXX_STR("0")));
		if (threadCount <= 0)
			threadCount = std::thread::hardware_concurrency() - 2;
		return threadCount;
	}

	static double warmUpSeconds()
	{
		auto milliseconds = helpers::StringHelper::toInt
			(helpers::OptionConverter::getSystemProperty
				(LOG4CXX_STR("LOG4CXX_BENCHMARK_WARM_UP_MILLISECONDS"), LOG4CXX_STR("0")));
		if (milliseconds <= 0)
			milliseconds = 100;
		return milliseconds / 1000;
	}

};

BENCHMARK_DEFINE_F(benchmarker, logDisabledTrace)(benchmark::State& state)
{
	m_logger->setLevel(Level::getDebug());
	for (auto _ : state)
	{
		LOG4CXX_TRACE( m_logger, LOG4CXX_STR("This is a static string to see what happens"));
	}
}
BENCHMARK_REGISTER_F(benchmarker, logDisabledTrace)->Name("Testing disabled logging request")->MinWarmUpTime(benchmarker::warmUpSeconds());
BENCHMARK_REGISTER_F(benchmarker, logDisabledTrace)->Name("Testing disabled logging request")->Threads(benchmarker::threadCount());

BENCHMARK_DEFINE_F(benchmarker, logStaticString)(benchmark::State& state)
{
	m_logger->setLevel(Level::getInfo());
	for (auto _ : state)
	{
		LOG4CXX_INFO( m_logger, LOG4CXX_STR("This is a static string to see what happens"));
	}
}
BENCHMARK_REGISTER_F(benchmarker, logStaticString)->Name("Logging static string");

#if LOG4CXX_HAS_FMT
BENCHMARK_DEFINE_F(benchmarker, logStaticStringFMT)(benchmark::State& state)
{
	for (auto _ : state)
	{
		LOG4CXX_INFO_FMT(m_logger, "This is a static string to see what happens", 0);
	}
}
BENCHMARK_REGISTER_F(benchmarker, logStaticStringFMT)->Name("Logging static string with FMT");

BENCHMARK_DEFINE_F(benchmarker, logIntValueFMT)(benchmark::State& state)
{
	int x = 0;
	for (auto _ : state)
	{
		LOG4CXX_INFO_FMT( m_logger, "Hello: msg number {}", ++x);
	}
}
BENCHMARK_REGISTER_F(benchmarker, logIntValueFMT)->Name("Logging int value with FMT");
BENCHMARK_REGISTER_F(benchmarker, logIntValueFMT)->Name("Logging int value with FMT")->Threads(benchmarker::threadCount());

BENCHMARK_DEFINE_F(benchmarker, logIntPlusFloatValueFMT)(benchmark::State& state)
{
	int x = 0;
	for (auto _ : state)
	{
		auto f = static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
		LOG4CXX_INFO_FMT( m_logger, "Hello: msg number {} pseudo-random float {:.3f}", ++x, f);
	}
}
BENCHMARK_REGISTER_F(benchmarker, logIntPlusFloatValueFMT)->Name("Logging int+float with FMT");
BENCHMARK_REGISTER_F(benchmarker, logIntPlusFloatValueFMT)->Name("Logging int+float with FMT")->Threads(benchmarker::threadCount());
#endif

BENCHMARK_DEFINE_F(benchmarker, logIntValueStream)(benchmark::State& state)
{
	int x = 0;
	for (auto _ : state)
	{
		LOG4CXX_INFO( m_logger, "Hello: msg number " << ++x);
	}
}
BENCHMARK_REGISTER_F(benchmarker, logIntValueStream)->Name("Logging int value with std::ostream");
BENCHMARK_REGISTER_F(benchmarker, logIntValueStream)->Name("Logging int value with std::ostream")->Threads(benchmarker::threadCount());

BENCHMARK_DEFINE_F(benchmarker, logIntPlusFloatStream)(benchmark::State& state)
{
	int x = 0;
	for (auto _ : state)
	{
		auto f = static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
		LOG4CXX_INFO( m_logger, "Hello: msg number " << ++x
			<< " pseudo-random float " << std::setprecision(3) << std::fixed << f);
	}
}
BENCHMARK_REGISTER_F(benchmarker, logIntPlusFloatStream)->Name("Logging int+float with std::ostream");
BENCHMARK_REGISTER_F(benchmarker, logIntPlusFloatStream)->Name("Logging int+float with std::ostream")->Threads(benchmarker::threadCount());

template <class ...Args>
void logWithConversionPattern(benchmark::State& state, Args&&... args)
{
    auto args_tuple = std::make_tuple(std::move(args)...);
	LogString conversionPattern = std::get<0>(args_tuple);

	PatternLayoutPtr pattern(new PatternLayout);
	pattern->setConversionPattern( conversionPattern );
	auto logger = Logger::getLogger( LOG4CXX_STR("bench_logger") );
	logger->getAppender(LOG4CXX_STR("NullWriterAppender"))->setLayout(pattern);

	int x = 0;
	for (auto _ : state)
	{
		LOG4CXX_INFO( logger, LOG4CXX_STR("Hello m_logger: msg number ") << ++x);
	}
}
BENCHMARK_CAPTURE(logWithConversionPattern, NoFormat, LOG4CXX_STR("%m%n"))->Name("NoFormat pattern: %m%n");
BENCHMARK_CAPTURE(logWithConversionPattern, DateOnly, LOG4CXX_STR("[%d] %m%n"))->Name("DateOnly pattern: [%d] %m%n");
BENCHMARK_CAPTURE(logWithConversionPattern, DateClassLevel, LOG4CXX_STR("[%d] [%c] [%p] %m%n"))->Name("DateClassLevel pattern: [%d] [%c] [%p] %m%n");

static void SetAsyncAppender(const benchmark::State& state)
{
	LoggerPtr logger = Logger::getLogger( LOG4CXX_STR("bench_logger") );
	logger->removeAllAppenders();
	logger->setAdditivity( false );
	logger->setLevel( Level::getInfo() );

	PatternLayoutPtr pattern(new PatternLayout);
	pattern->setConversionPattern(LOG4CXX_STR("%m%n"));

	NullWriterAppenderPtr nullWriter(new NullWriterAppender);
	nullWriter->setLayout( pattern );
	AsyncAppenderPtr asyncAppender = AsyncAppenderPtr(new AsyncAppender());
	asyncAppender->addAppender(nullWriter);
	asyncAppender->setBufferSize(5);
	helpers::Pool p;
	asyncAppender->activateOptions(p);
	logger->addAppender(asyncAppender);
}
BENCHMARK_REGISTER_F(benchmarker, logIntValueStream)->Name("Logging int value with std::ostream to AsyncAppender")->Setup(SetAsyncAppender);
BENCHMARK_REGISTER_F(benchmarker, logIntValueStream)->Name("Logging int value with std::ostream to AsyncAppender")->Threads(benchmarker::threadCount());

BENCHMARK_MAIN();

