/*
 * 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 0.2 sec to ensure the file is really gone on Windows
		apr_sleep(200000);
	}

	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(m_pool));
		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(m_pool));
		// 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, m_pool);
		of.flush(m_pool);
		of.close(m_pool);

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

LOGUNIT_TEST_SUITE_REGISTRATION(AutoConfigureTestCase);
