/*
 * 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 <apr_file_io.h>
#include <apr_time.h>
#include <log4cxx/logger.h>
#include <log4cxx/logmanager.h>
#include <log4cxx/helpers/bytebuffer.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/helpers/fileoutputstream.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx-qt/configuration.h>
#include <log4cxx-qt/transcoder.h>
#include <QCoreApplication>
#include <QFileInfo>

using namespace log4cxx;

LOGUNIT_CLASS(QtConfigurationTestCase)
{
	LOGUNIT_TEST_SUITE(QtConfigurationTestCase);
	LOGUNIT_TEST(test1);
	LOGUNIT_TEST_SUITE_END();
	helpers::Pool m_pool;
	char m_buf[2048];
	QString m_configFile;
	spi::ConfigurationStatus m_status;
public:

	void copyPropertyFile(const LogString& lsDestDir)
	{
		LOG4CXX_ENCODE_CHAR(destDir, lsDestDir);
		auto status = apr_file_copy
		   ( "input/qtConfigurationTest.properties"
		   , (destDir + "/qtConfigurationTest.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("/qtConfigurationTest.properties"), status));
	}

	void setUp()
	{
		int argc{ 0 };
		char* argv[] = {nullptr};
		static QCoreApplication init_once{argc, argv};
		auto lsTempDir = helpers::OptionConverter::getSystemProperty(LOG4CXX_STR("TEMP"), LOG4CXX_STR("/tmp"));
		copyPropertyFile(lsTempDir);
		LOG4CXX_ENCODE_QSTRING(qTempDir, lsTempDir);
		QVector<QString> paths
			{ qTempDir
			};
		QVector<QString> names
			{ QString("qtConfigurationTest.properties")
			};
		std::tie(m_status, m_configFile) = qt::Configuration::configureFromFileAndWatch(paths, names);
	}

	void tearDown()
	{
		LogManager::shutdown();
		apr_file_remove(m_configFile.toUtf8().constData(), m_pool.getAPRPool());
		// wait 0.2 sec to ensure the file is really gone on Windows
		apr_sleep(200000);
	}

	void test1()
	{
		LOGUNIT_ASSERT_EQUAL(m_status, spi::ConfigurationStatus::Configured);
		auto debugLogger1 = LogManager::getLogger(LOG4CXX_STR("test1"));
		LOGUNIT_ASSERT(debugLogger1);
		LOGUNIT_ASSERT(!debugLogger1->isDebugEnabled());
		auto debugLogger2 = LogManager::getLogger(LOG4CXX_STR("test2"));
		LOGUNIT_ASSERT(debugLogger2);
		LOGUNIT_ASSERT(debugLogger2->isDebugEnabled());
		LOGUNIT_ASSERT(QFileInfo(m_configFile).exists());
		// wait 1 sec to ensure the modification time is different to creation date
		for (auto i : {1, 2})
		{
			QCoreApplication::processEvents();
			apr_sleep(500000); // 500 ms
		}
		auto debugLogger = LogManager::getLogger(LOG4CXX_STR("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.test3=DEBUG\n"; *p; ++p)
		{
			bbuf.put(*p);
			++sz;
		}
		bbuf.flip();
		LOG4CXX_DECODE_QSTRING(lsConfigFile, m_configFile);
		helpers::FileOutputStream of(lsConfigFile, true);
		of.write(bbuf, m_pool);
		of.flush(m_pool);
		of.close(m_pool);
		helpers::LogLog::debug(LOG4CXX_STR("Updated ") + lsConfigFile);

		// wait 0.1 sec for the change to be noticed
		for (auto i : {1, 2})
		{
			QCoreApplication::processEvents();
			apr_sleep(50000); // 50 ms
		}
		LOGUNIT_ASSERT(debugLogger->isDebugEnabled());
	}
};

LOGUNIT_TEST_SUITE_REGISTRATION(QtConfigurationTestCase);
