/*
 * 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 "logunit.h"
#include <log4cxx/logger.h>
#include <log4cxx/logmanager.h>
#include <log4cxx/fileappender.h>
#include <log4cxx/defaultconfigurator.h>
#include <log4cxx/helpers/bytebuffer.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/helpers/fileinputstream.h>
#include <log4cxx/helpers/fileoutputstream.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/filesystempath.h>
#include <log4cxx/helpers/transcoder.h>
#include <thread>
#include <apr_file_io.h>
#include <apr_file_info.h>
#include "apr_time.h"

#define LOGUNIT_TEST_THREADS(testName, threadCount) \
	class testName ## ThreadTestRegistration { \
		public: \
			testName ## ThreadTestRegistration() { \
				ThisFixture::getSuite()->addTest(#testName, &testName ## ThreadTestRegistration :: run); \
			} \
			static void run(abts_case* tc, void*) { \
				std::vector<std::thread> threads; \
				for (auto i = threadCount; 0 < i; --i) \
					threads.emplace_back( [tc]() { \
						LogUnit::runTest<ThisFixture>(tc, &ThisFixture::testName); \
					} ); \
				while (!threads.empty()) { \
					threads.back().join(); \
					threads.pop_back(); \
				} \
			} \
	} register ## testName ## ThreadTest

using namespace log4cxx;

LOGUNIT_CLASS(AutoConfigureTestCase)
{
	LOGUNIT_TEST_SUITE(AutoConfigureTestCase);
	LOGUNIT_TEST(testSetup);
	LOGUNIT_TEST(test1);
	LOGUNIT_TEST(test2);
	LOGUNIT_TEST_SUITE_END();
#ifdef _DEBUG
	struct Fixture
	{
		Fixture() {
			helpers::LogLog::setInternalDebugging(true);
		}
	} suiteFixture;
#endif
	helpers::Pool m_pool;
	char m_buf[2048];
	LogString m_configFile;
	spi::ConfigurationStatus m_status;
public:

	void copyPropertyFile(const LogString& lsDestDir, const LogString& lsFileName)
	{
		LOG4CXX_ENCODE_CHAR(destDir, lsDestDir);
		LOG4CXX_ENCODE_CHAR(fileName, lsFileName);
		auto status = apr_file_copy
		   ( "input/autoConfigureTest.properties"
		   , (destDir + "/" + fileName + ".properties").c_str()
		   , APR_FPROT_UREAD | APR_FPROT_UWRITE
		   , m_pool.getAPRPool()
		   );
		if (APR_SUCCESS != status)
		   helpers::LogLog::warn(helpers::Exception::makeMessage(lsDestDir + LOG4CXX_STR("/") + lsFileName + LOG4CXX_STR(".properties"), status));
	}

	void setUp()
	{
#if !LOG4CXX_HAS_FILESYSTEM_PATH
		spi::Configurator::properties().setProperty(LOG4CXX_STR("PROGRAM_FILE_PATH.STEM"), LOG4CXX_STR("autoconfiguretestcase"));
#endif
		auto fileName = spi::Configurator::properties().getProperty(LOG4CXX_STR("PROGRAM_FILE_PATH.STEM"));
		auto lsTempDir = helpers::OptionConverter::getSystemProperty(LOG4CXX_STR("TEMP"), LOG4CXX_STR("/tmp"));
		copyPropertyFile(lsTempDir, fileName);
		DefaultConfigurator::setConfigurationWatchSeconds(1);
		std::vector<LogString> paths
			{ lsTempDir
			};
		std::vector<LogString> names
			{ LOG4CXX_STR("${PROGRAM_FILE_PATH.STEM}.properties")
			};
		std::tie(m_status, m_configFile) = DefaultConfigurator::configureFromFile(paths, names);
	}

	void tearDown()
	{
		LogManager::shutdown();
		LOG4CXX_ENCODE_CHAR(configFile, m_configFile);
		apr_file_remove(configFile.c_str(), m_pool.getAPRPool());
		// wait 1 sec to ensure the WatchDog will reload the configuration
		apr_sleep(1000000);
	}

	void testSetup()
	{
		auto fa = LOG4CXX_NS::cast<FileAppender>(LogManager::getRootLogger()->getAppender(LOG4CXX_STR("A1")));
		LOGUNIT_ASSERT(fa);
		auto fileName = spi::Configurator::properties().getProperty(LOG4CXX_STR("PROGRAM_FILE_PATH.STEM"));
		File logFile(fa->getFile());
		LOGUNIT_ASSERT_EQUAL(fileName + LOG4CXX_STR(".log"), logFile.getName());
	}

	void test1()
	{
		LOGUNIT_ASSERT_EQUAL(m_status, spi::ConfigurationStatus::Configured);
		LOGUNIT_ASSERT(File(m_configFile).exists());
		auto debugLogger1 = LogManager::getLogger(LOG4CXX_STR("AutoConfig.test1"));
		LOGUNIT_ASSERT(debugLogger1);
		LOGUNIT_ASSERT(!debugLogger1->isDebugEnabled());
		auto debugLogger2 = LogManager::getLogger(LOG4CXX_STR("AutoConfig.test2"));
		LOGUNIT_ASSERT(debugLogger2);
		LOGUNIT_ASSERT(debugLogger2->isDebugEnabled());
	}

	void test2()
	{
		LOGUNIT_ASSERT_EQUAL(m_status, spi::ConfigurationStatus::Configured);
		LOGUNIT_ASSERT(File(m_configFile).exists());
		// wait 2 sec to ensure the modification time is different to that held in the WatchDog
		apr_sleep(2000000);
		auto debugLogger = LogManager::getLogger(LOG4CXX_STR("AutoConfig.test3"));
		LOGUNIT_ASSERT(debugLogger);
		LOGUNIT_ASSERT(!debugLogger->isDebugEnabled());

		// Append a configuration for test3 logger
		helpers::ByteBuffer bbuf(m_buf, sizeof(m_buf));
		int sz = 0;
		for (const char* p = "\nlog4j.logger.AutoConfig.test3=DEBUG\n"; *p; ++p)
		{
			bbuf.put(*p);
			++sz;
		}
		bbuf.flip();
		helpers::FileOutputStream of(m_configFile, true);
		of.write(bbuf);
		of.flush();
		of.close();

		// wait 1.5 sec for the change to be noticed
		apr_sleep(1500000);
		LOGUNIT_ASSERT(debugLogger->isDebugEnabled());
	}
};

LOGUNIT_TEST_SUITE_REGISTRATION(AutoConfigureTestCase);
