/*
 * 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/logger.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/patternlayout.h>
#include <log4cxx/consoleappender.h>
#include <log4cxx/helpers/transcoder.h>

#include <string>
#include <thread>

#if LOG4CXX_USING_STD_FORMAT
#include <format>
#else
#include <fmt/core.h>
#include <fmt/chrono.h>
#include <fmt/ostream.h>
#endif

#include "log4cxxbenchmarker.h"
using log4cxx::LogString;

static log4cxx::LoggerPtr console = log4cxx::Logger::getLogger( "console" );
static std::vector<uint64_t> results;
static std::mutex results_mutex;

static void benchmark_function( const std::string& name, void (*fn)(int), int howmany )
{
	using std::chrono::duration;
	using std::chrono::duration_cast;
	using std::chrono::high_resolution_clock;

	auto start = high_resolution_clock::now();
	fn(howmany);
	auto delta = high_resolution_clock::now() - start;
	auto delta_d = duration_cast<duration<double>>(delta).count();

	std::unique_lock<std::mutex> lk(results_mutex);
	results.push_back( uint64_t(howmany / delta_d) );
	LOG4CXX_INFO_FMT( console, "Log4cxx {} Elapsed: {:.4} secs {:L}/sec",
		name,
		delta_d,
		results.back());
}

static void benchmark_conversion_pattern( const std::string& name,
	const std::string& conversion_pattern,
	void(*fn)(const LogString&, int),
	int howmany)
{
	using std::chrono::duration;
	using std::chrono::duration_cast;
	using std::chrono::high_resolution_clock;

	auto start = high_resolution_clock::now();
	LOG4CXX_DECODE_CHAR(conversion_patternLS, conversion_pattern);
	fn(conversion_patternLS, howmany);
	auto delta = high_resolution_clock::now() - start;
	auto delta_d = duration_cast<duration<double>>(delta).count();

	std::unique_lock<std::mutex> lk(results_mutex);
	results.push_back( uint64_t(howmany / delta_d) );
	LOG4CXX_INFO_FMT( console, "Log4cxx {} pattern: {} Elapsed: {:.4} secs {:L}/sec",
		name,
		conversion_pattern,
		delta_d,
		results.back());
}

static void bench_log4cxx_single_threaded(int iters)
{
	LOG4CXX_INFO(console, LOG4CXX_STR("**************************************************************"));
	LOG4CXX_INFO_FMT(console, "Benchmarking Single threaded: {} messages", iters );
	LOG4CXX_INFO(console, LOG4CXX_STR("**************************************************************"));

	benchmark_conversion_pattern( "NoFormat", "%m%n", &log4cxxbenchmarker::logWithConversionPattern, iters );
	benchmark_conversion_pattern( "DateOnly", "[%d] %m%n", &log4cxxbenchmarker::logWithConversionPattern, iters );
	benchmark_conversion_pattern( "DateClassLevel", "[%d] [%c] [%p] %m%n", &log4cxxbenchmarker::logWithConversionPattern, iters );

	benchmark_function( "Logging with FMT", &log4cxxbenchmarker::logWithFMT, iters );
	benchmark_function( "Logging static string", &log4cxxbenchmarker::logStaticString, iters );
	benchmark_function( "Logging static string with FMT", &log4cxxbenchmarker::logStaticStringFMT, iters );
	benchmark_function( "Logging disabled debug", &log4cxxbenchmarker::logDisabledDebug, iters );
	benchmark_function( "Logging disabled trace", &log4cxxbenchmarker::logDisabledTrace, iters );
	benchmark_function( "Logging enabled debug", &log4cxxbenchmarker::logEnabledDebug, iters );
	benchmark_function( "Logging enabled trace", &log4cxxbenchmarker::logEnabledTrace, iters );
}

static void bench_log4cxx_multi_threaded(size_t threads, int iters)
{
	LOG4CXX_INFO(console, LOG4CXX_STR("**************************************************************"));
	LOG4CXX_INFO_FMT(console, "Benchmarking multithreaded threaded: {} messages/thread, {} threads", iters, threads );
	LOG4CXX_INFO(console, LOG4CXX_STR("**************************************************************"));

	std::vector<std::thread> runningThreads;

	auto logger = log4cxxbenchmarker::logSetupMultithreaded();

	for ( size_t x = 0; x < threads; x++ )
	{
		runningThreads.push_back( std::thread( [iters]()
		{
			benchmark_function( "Logging with FMT MT", &log4cxxbenchmarker::logWithFMTMultithreaded, iters );
		}) );
	}

	for ( std::thread& th : runningThreads )
	{
		th.join();
	}
}

static void bench_log4cxx_multi_threaded_disabled(size_t threads, int iters)
{
	LOG4CXX_INFO(console, LOG4CXX_STR("**************************************************************"));
	LOG4CXX_INFO_FMT(console, "Benchmarking multithreaded disabled: {} messages/thread, {} threads", iters, threads );
	LOG4CXX_INFO(console, LOG4CXX_STR("**************************************************************"));

	std::vector<std::thread> runningThreads;

	auto logger = log4cxxbenchmarker::logSetupMultithreaded();

	for ( size_t x = 0; x < threads; x++ )
	{
		runningThreads.push_back( std::thread( [iters]()
		{
			benchmark_function( "Logging disabled MT", &log4cxxbenchmarker::logDisabledMultithreaded, iters );
		}) );
	}

	for ( std::thread& th : runningThreads )
	{
		th.join();
	}
}

int main(int argc, char* argv[])
{
	int iters = 1000000;
	size_t threads = 4;
	size_t max_threads = 32;

	std::setlocale( LC_ALL, "" ); /* Set locale for C functions */
	std::locale::global(std::locale("")); /* set locale for C++ functions */

	console->setAdditivity( false );
	log4cxx::PatternLayoutPtr pattern( new log4cxx::PatternLayout() );
	pattern->setConversionPattern( LOG4CXX_STR("%m%n") );

	log4cxx::ConsoleAppenderPtr consoleWriter( new log4cxx::ConsoleAppender );
	consoleWriter->setLayout( pattern );
	consoleWriter->setTarget( LOG4CXX_STR("System.out") );
	log4cxx::helpers::Pool p;
	consoleWriter->activateOptions(p);

	console->addAppender( consoleWriter );

	if (argc > 1)
	{
		iters = std::stoi(argv[1]);
	}

	if (argc > 2)
	{
		threads = std::stoul(argv[2]);
	}

	if (threads > max_threads)
	{
		LOG4CXX_ERROR_FMT(console, "Too many threads specified(max: {})", max_threads);
		return 1;
	}

	LOG4CXX_INFO_FMT(console, "Benchmarking library only(no writing out):", 0);
	bench_log4cxx_single_threaded(iters);
	bench_log4cxx_multi_threaded(threads, iters);
	bench_log4cxx_multi_threaded_disabled(threads, iters);

	LOG4CXX_INFO_FMT(console, "Results for use in spreadsheet:", 0);

	for ( uint64_t result : results )
	{
		LOG4CXX_INFO_FMT(console, "{}", result );
	}

	return 0;
}
