/*
 * 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 "../util/compare.h"
#include "../logunit.h"
#include "../insertwide.h"
#include <log4cxx/logmanager.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/rolling/multiprocessrollingfileappender.h>
#include <log4cxx/rolling/sizebasedtriggeringpolicy.h>
#include <log4cxx/helpers/strftimedateformat.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/date.h>
#include <log4cxx/helpers/fileoutputstream.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/stringhelper.h>
#include <filesystem>
#include <fstream>
#include <apr_thread_proc.h>

using namespace LOG4CXX_NS;

auto getLogger(const std::string& name) -> LoggerPtr {
	static struct log4cxx_initializer {
		log4cxx_initializer() {
			xml::DOMConfigurator::configure("input/rolling/multiprocess.xml");
		}
		~log4cxx_initializer() {
			LogManager::shutdown();
		}
	} initAndShutdown;
	return name.empty()
		? LogManager::getRootLogger()
		: LogManager::getLogger(name);
}

LOGUNIT_CLASS(MultiprocessRollingTest)
{
	LOGUNIT_TEST_SUITE(MultiprocessRollingTest);
	LOGUNIT_TEST(test1);
	LOGUNIT_TEST(test2);
	LOGUNIT_TEST(test3);
	LOGUNIT_TEST(test4);
	LOGUNIT_TEST_SUITE_END();

public:
	/**
	 * Test a numeric rolling policy with a log level based trigger.
	 */
	void test1()
	{
		auto logger = getLogger("Test1");
		for (int i = 0; i < 25; i++)
		{
			char msg[10];
#if defined(__STDC_LIB_EXT1__) || defined(__STDC_SECURE_LIB__)
			strcpy_s(msg, sizeof msg, "Hello---?");
#else
			strcpy(msg, "Hello---?");
#endif

			if (i < 10)
			{
				msg[8] = (char) ('0' + i);
				LOG4CXX_DEBUG(logger, msg);
			}
			else if (i < 100)
			{
				msg[7] = (char) ('0' + (i / 10));
				msg[8] = (char) ('0' + (i % 10));

				if ((i % 10) == 0)
				{
					LOG4CXX_WARN(logger, msg);
				}
				else
				{
					LOG4CXX_DEBUG(logger, msg);
				}
			}
		}

		LogString baseName = LOG4CXX_STR("output/rolling/multiprocess-test");
		LOGUNIT_ASSERT_EQUAL(true,
			Compare::compare(baseName + LOG4CXX_STR(".log"), LogString(LOG4CXX_STR("witness/rolling/multiprocess-test.log"))));
		LOGUNIT_ASSERT_EQUAL(true,
			Compare::compare(baseName + LOG4CXX_STR(".0"), LogString(LOG4CXX_STR("witness/rolling/multiprocess-test.0"))));
		LOGUNIT_ASSERT_EQUAL(true,
			Compare::compare(baseName + LOG4CXX_STR(".1"), LogString(LOG4CXX_STR("witness/rolling/multiprocess-test.1"))));
	}

	/**
	 * Test a time based rolling policy with a sized based trigger.
	 */
	void test2()
	{
		std::string expectedPrefix{ "multiprocess-2-" };
		// remove any previously generated files
		std::filesystem::path outputDir("output/rolling");
		if (!exists(outputDir))
			;
		else for (auto const& dir_entry : std::filesystem::directory_iterator{outputDir})
		{
			std::string filename(dir_entry.path().filename().string());
			if (expectedPrefix.size() < filename.size() &&
				filename.substr(0, expectedPrefix.size()) == expectedPrefix)
				std::filesystem::remove(dir_entry);
		}
		auto logger = getLogger("Test2");
		auto approxBytesPerLogEvent = 40 + 23;
		auto requiredLogFileCount = 3;
		size_t approxBytesPerLogFile = 1000;
		if (auto pAppender = LOG4CXX_NS::cast<rolling::RollingFileAppender>(logger->getAppender(LOG4CXX_STR("DATED"))))
		{
			if (auto pPolicy = LOG4CXX_NS::cast<rolling::SizeBasedTriggeringPolicy>(pAppender->getTriggeringPolicy()))
				approxBytesPerLogFile = pPolicy->getMaxFileSize();
		}
		auto requiredLogEventCount = (approxBytesPerLogFile * requiredLogFileCount + approxBytesPerLogEvent - 1) / approxBytesPerLogEvent;
		for ( size_t x = 0; x < requiredLogEventCount; x++ )
		{
			LOG4CXX_INFO( logger, "This is test message " << x );
		}

		// Count rolled files
		LOG4CXX_DECODE_CHAR(expectedPrefixLS, expectedPrefix);
		helpers::Pool p;
		helpers::StrftimeDateFormat(LOG4CXX_STR("%Y-%m-%d")).format(expectedPrefixLS, helpers::Date::currentTime(), p);
		LOG4CXX_ENCODE_CHAR(rolledPrefix, expectedPrefixLS);
		int fileCount = 0;
		for (auto const& dir_entry : std::filesystem::directory_iterator{"output/rolling"})
		{
			std::string filename(dir_entry.path().filename().string());
			if (rolledPrefix.size() < filename.size() &&
				filename.substr(0, rolledPrefix.size()) == rolledPrefix)
				++fileCount;
		}
		LOGUNIT_ASSERT(1 < fileCount);
	}

	/**
	 * Generate about 30 rollovers per process using a time based rolling policy with a sized based trigger.
	 */
	void test3()
	{
		auto logger = getLogger("Test3");
		auto approxBytesPerLogEvent = 40 + 23;
		auto requiredLogFileCount = 30;
		size_t approxBytesPerLogFile = 1000;
		if (auto pAppender = LOG4CXX_NS::cast<rolling::RollingFileAppender>(logger->getAppender(LOG4CXX_STR("DATED-UNCOMPRESSED"))))
		{
			if (auto pPolicy = LOG4CXX_NS::cast<rolling::SizeBasedTriggeringPolicy>(pAppender->getTriggeringPolicy()))
				approxBytesPerLogFile = pPolicy->getMaxFileSize();
		}
		auto requiredLogEventCount = (approxBytesPerLogFile * requiredLogFileCount + approxBytesPerLogEvent - 1) / approxBytesPerLogEvent;
		for ( size_t x = 0; x < requiredLogEventCount; x++ )
		{
			LOG4CXX_INFO( logger, "This is test message " << x );
		}
	}

	/**
	 * Concurrently use a time based rolling policy with a sized based trigger.
	 */
	void test4()
	{
		std::string expectedPrefix("multiprocess-3");
		// remove any previously generated files
		std::filesystem::path outputDir("output/rolling");
		if (!exists(outputDir))
			;
		else for (auto const& dir_entry : std::filesystem::directory_iterator{outputDir})
		{
			std::string filename(dir_entry.path().filename().string());
			if (expectedPrefix.size() < filename.size() &&
				filename.substr(0, expectedPrefix.size()) == expectedPrefix)
				std::filesystem::remove(dir_entry);
		}
		helpers::FileOutputStream output(LOG4CXX_STR("output/rolling/multiprocess-test4-child.log"), false);
		auto thisProgram = GetExecutableFileName();
		bool thisProgramExists = std::filesystem::exists(thisProgram);
		if (!thisProgramExists && helpers::LogLog::isDebugEnabled())
		{
			LOG4CXX_DECODE_CHAR(lsProgram, thisProgram);
			helpers::LogLog::debug(LOG4CXX_STR("thisProgram: ") + lsProgram);
		}
		LOGUNIT_ASSERT(thisProgramExists);
		const char* args[] = {thisProgram.c_str(), "test3", 0};
		helpers::Pool p;
		apr_procattr_t* attr = NULL;
		setTestAttributes(&attr, output.getFilePtr(), p);
		apr_proc_t pid[5];
		auto startTime = helpers::Date::currentTime();
		for (auto i : {0, 1, 2, 3, 4})
			startTestInstance(&pid[i], attr, args, p);
		for (auto i : {0, 1, 2, 3, 4})
		{
			int exitCode;
			apr_exit_why_e reason;
			apr_proc_wait(&pid[i], &exitCode, &reason, APR_WAIT);
			if (exitCode != 0 && helpers::LogLog::isDebugEnabled())
			{
				LogString msg = LOG4CXX_STR("child: ");
				helpers::StringHelper::toString(i, p, msg);
				msg += LOG4CXX_STR("; exit code: ");
				helpers::StringHelper::toString(exitCode, p, msg);
				msg += LOG4CXX_STR("; reason: ");
				helpers::StringHelper::toString(reason, p, msg);
				helpers::LogLog::debug(msg);
			}
			LOGUNIT_ASSERT_EQUAL(exitCode, 0);
		}
		if (helpers::LogLog::isDebugEnabled())
		{
			LogString msg;
			auto currentTime = helpers::Date::currentTime();
			msg += LOG4CXX_STR("elapsed ");
			helpers::StringHelper::toString(currentTime - startTime, p, msg);
			helpers::LogLog::debug(msg);
		}

		// Check all messages are saved to files
		std::string expectedSuffix(".log");
		std::vector<int> messageCount;
		std::map<long long, int> perThreadMessageCount;
		for (auto const& dir_entry : std::filesystem::directory_iterator{"output/rolling"})
		{
			std::string filename(dir_entry.path().filename().string());
			if (expectedPrefix.size() + expectedSuffix.size() <= filename.size()
				&& filename.substr(0, expectedPrefix.size()) == expectedPrefix
				&& filename.substr(filename.size() - expectedSuffix.size()) == expectedSuffix)
			{
				auto initialPerThreadMessageCount = perThreadMessageCount;
				std::ifstream input(dir_entry.path());
				for (std::string line; std::getline(input, line);)
				{
					 auto pos = line.rfind(' ');
					 if (line.npos != pos && pos + 1 < line.size())
					 {
						try
						{
							auto msgNumber = std::stoull(line.substr(pos));
							if (messageCount.size() <= msgNumber)
								messageCount.resize(msgNumber + 1);
							++messageCount[msgNumber];
						}
						catch (std::exception const& ex)
						{
							LogString msg;
							helpers::Transcoder::decode(ex.what(), msg);
							msg += LOG4CXX_STR(" processing\n");
							helpers::Transcoder::decode(line, msg);
							helpers::LogLog::warn(msg);
						}
					 }
					 pos = line.find(" [0x");
					 if (line.npos != pos && pos + 4 < line.size())
					 {
						try
						{
							auto threadNumber = std::stoll(line.substr(pos + 4), 0, 16);
							++perThreadMessageCount[threadNumber];
						}
						catch (std::exception const& ex)
						{
							LogString msg;
							helpers::Transcoder::decode(ex.what(), msg);
							msg += LOG4CXX_STR(" processing\n");
							helpers::Transcoder::decode(line, msg);
							helpers::LogLog::warn(msg);
						}
					 }
				}
				if (helpers::LogLog::isDebugEnabled())
				{
					LogString msg;
					helpers::Transcoder::decode(dir_entry.path().filename().string(), msg);
					msg += LOG4CXX_STR(": perThreadMessageCount ");
					for (auto item : perThreadMessageCount)
					{
						msg += logchar(' ');
						helpers::StringHelper::toString(item.second - initialPerThreadMessageCount[item.first], p, msg);
					}
					helpers::LogLog::debug(msg);
				}
			}
		}
		if (helpers::LogLog::isDebugEnabled())
		{
			LogString msg(LOG4CXX_STR("messageCount "));
			for (auto item : messageCount)
			{
				msg += logchar(' ');
				helpers::StringHelper::toString(item, p, msg);
			}
			helpers::LogLog::debug(msg);
		}
		if (helpers::LogLog::isDebugEnabled())
		{
			LogString msg(LOG4CXX_STR("perThreadMessageCount "));
			for (auto item : perThreadMessageCount)
			{
				msg += logchar(' ');
				helpers::StringHelper::toString(item.second, p, msg);
			}
			helpers::LogLog::debug(msg);
		}
		for (auto& count : messageCount)
			LOGUNIT_ASSERT_EQUAL(count, messageCount.front());
	}

private:

	void setTestAttributes(apr_procattr_t** attr, apr_file_t* output, helpers::Pool& p)
	{
		if (apr_procattr_create(attr, p.getAPRPool()) != APR_SUCCESS)
		{
			LOGUNIT_FAIL("apr_procattr_create");
		}
		if (apr_procattr_cmdtype_set(*attr, APR_PROGRAM) != APR_SUCCESS)
		{
			LOGUNIT_FAIL("apr_procattr_cmdtype_set");
		}
		if (apr_procattr_child_out_set(*attr, output, NULL) != APR_SUCCESS)
		{
			LOGUNIT_FAIL("apr_procattr_child_out_set");
		}
		if (apr_procattr_child_err_set(*attr, output, NULL) != APR_SUCCESS)
		{
			LOGUNIT_FAIL("apr_procattr_child_err_set");
		}
	}

	void startTestInstance(apr_proc_t* pid, apr_procattr_t* attr, const char** argv, helpers::Pool& p)
	{
		if (apr_proc_create(pid, argv[0], argv, NULL, attr, p.getAPRPool()) == APR_SUCCESS)
		{
			apr_sleep(1000);    // 1 millisecond
		}
		else
		{
			LOGUNIT_FAIL("apr_proc_create");
		}
	}

	std::string GetExecutableFileName()
	{
		auto lsProgramFilePath = spi::Configurator::properties().getProperty(LOG4CXX_STR("PROGRAM_FILE_PATH"));
		LOG4CXX_ENCODE_CHAR(programFilePath, lsProgramFilePath);
		return programFilePath;
	}
#ifdef _DEBUG
	struct Fixture
	{
		Fixture() {
			helpers::LogLog::setInternalDebugging(true);
		}
	} suiteFixture;
#endif

};

LOGUNIT_TEST_SUITE_REGISTRATION(MultiprocessRollingTest);
