/*
 * 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/logstring.h>
#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/integer.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/rolling/rolloverdescription.h>
#include <log4cxx/rolling/filerenameaction.h>
#include <log4cxx/rolling/gzcompressaction.h>
#include <log4cxx/rolling/zipcompressaction.h>
#include <log4cxx/pattern/integerpatternconverter.h>
#include <log4cxx/private/rollingpolicybase_priv.h>

using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::rolling;
using namespace LOG4CXX_NS::helpers;
using namespace LOG4CXX_NS::pattern;

#define priv static_cast<FixedWindowRollingPolicyPrivate*>(m_priv.get())

struct FixedWindowRollingPolicy::FixedWindowRollingPolicyPrivate : public RollingPolicyBasePrivate {
	FixedWindowRollingPolicyPrivate() :
		RollingPolicyBasePrivate(),
		minIndex(1),
		maxIndex(7),
		explicitActiveFile(false)
	{}

	int minIndex;
	int maxIndex;
	bool explicitActiveFile;
	bool throwIOExceptionOnForkFailure = true;
};

IMPLEMENT_LOG4CXX_OBJECT(FixedWindowRollingPolicy)

FixedWindowRollingPolicy::FixedWindowRollingPolicy() :
	RollingPolicyBase (std::make_unique<FixedWindowRollingPolicyPrivate>())
{
}

FixedWindowRollingPolicy::~FixedWindowRollingPolicy(){}

void FixedWindowRollingPolicy::setMaxIndex(int maxIndex1)
{
	priv->maxIndex = maxIndex1;
}

void FixedWindowRollingPolicy::setMinIndex(int minIndex1)
{
	priv->minIndex = minIndex1;
}

void FixedWindowRollingPolicy::setOption(const LogString& option,
	const LogString& value)
{
	if (StringHelper::equalsIgnoreCase(option,
			LOG4CXX_STR("MININDEX"),
			LOG4CXX_STR("minindex")))
	{
		priv->minIndex = OptionConverter::toInt(value, 1);
	}
	else if (StringHelper::equalsIgnoreCase(option,
			LOG4CXX_STR("MAXINDEX"),
			LOG4CXX_STR("maxindex")))
	{
		priv->maxIndex = OptionConverter::toInt(value, 7);
	}
	else if (StringHelper::equalsIgnoreCase(option,
			LOG4CXX_STR("THROWIOEXCEPTIONONFORKFAILURE"),
			LOG4CXX_STR("throwioexceptiononforkfailure")))
	{
		priv->throwIOExceptionOnForkFailure = OptionConverter::toBoolean(value, true);
	}
	else
	{
		RollingPolicyBase::setOption(option, value);
	}
}

/**
 * {@inheritDoc}
 */
void FixedWindowRollingPolicy::activateOptions(Pool& p)
{
	RollingPolicyBase::activateOptions(p);

	if (priv->maxIndex < priv->minIndex)
	{
		LogLog::warn(
			LOG4CXX_STR("MaxIndex  cannot be smaller than MinIndex."));
		priv->maxIndex = priv->minIndex;
	}

	if ((priv->maxIndex - priv->minIndex) > MAX_WINDOW_SIZE)
	{
		LogLog::warn(LOG4CXX_STR("Large window sizes are not allowed."));
		priv->maxIndex = priv->minIndex + MAX_WINDOW_SIZE;
	}

	PatternConverterPtr itc = getIntegerPatternConverter();

	if (itc == NULL)
	{
		throw IllegalStateException();
	}
}

/**
 * {@inheritDoc}
 */
RolloverDescriptionPtr FixedWindowRollingPolicy::initialize(
	const   LogString&  currentActiveFile,
	const   bool        append,
	Pool&       pool)
{
	LogString newActiveFile(currentActiveFile);
	priv->explicitActiveFile = false;

	if (currentActiveFile.length() > 0)
	{
		priv->explicitActiveFile = true;
		newActiveFile = currentActiveFile;
	}

	if (!priv->explicitActiveFile)
	{
		LogString buf;
		ObjectPtr obj = std::make_shared<Integer>(priv->minIndex);
		formatFileName(obj, buf, pool);
		newActiveFile = buf;
	}

	ActionPtr noAction;

	return std::make_shared<RolloverDescription>(newActiveFile, append, noAction, noAction);
}

/**
 * {@inheritDoc}
 */
RolloverDescriptionPtr FixedWindowRollingPolicy::rollover(
	const   LogString&  currentActiveFile,
	const   bool        append,
	Pool&       pool)
{
	RolloverDescriptionPtr desc;

	if (priv->maxIndex < 0)
	{
		return desc;
	}

	int purgeStart = priv->minIndex;

	if (!priv->explicitActiveFile)
	{
		purgeStart++;
	}

	if (!purge(purgeStart, priv->maxIndex, pool))
	{
		return desc;
	}

	LogString buf;
	ObjectPtr obj = std::make_shared<Integer>(purgeStart);
	formatFileName(obj, buf, pool);

	LogString renameTo(buf);
	LogString compressedName(renameTo);
	ActionPtr compressAction ;

	if(getCreateIntermediateDirectories()){
		File compressedFile(compressedName);
		File compressedParent (compressedFile.getParent(pool));
		compressedParent.mkdirs(pool);
	}

	if (StringHelper::endsWith(renameTo, LOG4CXX_STR(".gz")))
	{
		renameTo.resize(renameTo.size() - 3);
		GZCompressActionPtr comp = std::make_shared<GZCompressAction>(
					File().setPath(renameTo),
					File().setPath(compressedName),
					true);
		comp->setThrowIOExceptionOnForkFailure(priv->throwIOExceptionOnForkFailure);
		compressAction = comp;
	}
	else if (StringHelper::endsWith(renameTo, LOG4CXX_STR(".zip")))
	{
		renameTo.resize(renameTo.size() - 4);
		ZipCompressActionPtr comp = std::make_shared<ZipCompressAction>(
					File().setPath(renameTo),
					File().setPath(compressedName),
					true);
		comp->setThrowIOExceptionOnForkFailure(priv->throwIOExceptionOnForkFailure);
		compressAction = comp;
	}

	auto renameAction = std::make_shared<FileRenameAction>(
				File().setPath(currentActiveFile),
				File().setPath(renameTo),
				false);

	desc = std::make_shared<RolloverDescription>(
				currentActiveFile,  append,
				renameAction,       compressAction);

	return desc;
}

/**
 * Get index of oldest log file to be retained.
 * @return index of oldest log file.
 */
int FixedWindowRollingPolicy::getMaxIndex() const
{
	return priv->maxIndex;
}

/**
 * Get index of most recent log file.
 * @return index of oldest log file.
 */
int FixedWindowRollingPolicy::getMinIndex() const
{
	return priv->minIndex;
}


/**
 * Purge and rename old log files in preparation for rollover
 * @param lowIndex low index
 * @param highIndex high index.  Log file associated with high
 * index will be deleted if needed.
 * @return true if purge was successful and rollover should be attempted.
 */
bool FixedWindowRollingPolicy::purge(int lowIndex, int highIndex, Pool& p) const
{
	int suffixLength = 0;

	std::vector<FileRenameActionPtr> renames;
	LogString buf;
	ObjectPtr obj = std::make_shared<Integer>(lowIndex);
	formatFileName(obj, buf, p);

	LogString lowFilename(buf);

	if (lowFilename.compare(lowFilename.length() - 3, 3, LOG4CXX_STR(".gz")) == 0)
	{
		suffixLength = 3;
	}
	else if (lowFilename.compare(lowFilename.length() - 4, 4, LOG4CXX_STR(".zip")) == 0)
	{
		suffixLength = 4;
	}

	for (int i = lowIndex; i <= highIndex; i++)
	{
		File toRenameCompressed;
		toRenameCompressed.setPath(lowFilename);
		File toRenameBase;
		toRenameBase.setPath(lowFilename.substr(0, lowFilename.length() - suffixLength));
		File* toRename = &toRenameCompressed;
		bool isBase = false;
		bool exists = toRenameCompressed.exists(p);

		if (suffixLength > 0)
		{
			if (exists)
			{
				if (toRenameBase.exists(p))
				{
					toRenameBase.deleteFile(p);
				}
			}
			else
			{
				toRename = &toRenameBase;
				exists = toRenameBase.exists(p);
				isBase = true;
			}
		}

		if (exists)
		{
			//
			//    if at upper index then
			//        attempt to delete last file
			//        if that fails then abandon purge
			if (i == highIndex)
			{
				if (!toRename->deleteFile(p))
				{
					return false;
				}

				break;
			}

			//
			//   if intermediate index
			//     add a rename action to the list
			buf.erase(buf.begin(), buf.end());
			obj = std::make_shared<Integer>(i + 1);
			formatFileName(obj, buf, p);

			LogString highFilename(buf);
			LogString renameTo(highFilename);

			if (isBase)
			{
				renameTo =
					highFilename.substr(0, highFilename.length() - suffixLength);
			}

			renames.push_back(std::make_shared<FileRenameAction>(*toRename, File().setPath(renameTo), true));
			lowFilename = highFilename;
		}
		else
		{
			break;
		}
	}

	//
	//   work renames backwards
	//
	for (std::vector<FileRenameActionPtr>::reverse_iterator iter = renames.rbegin();
		iter != renames.rend();
		iter++)
	{

		try
		{
			if (!(*iter)->execute(p))
			{
				return false;
			}
		}
		catch (std::exception&)
		{
			LogLog::warn(LOG4CXX_STR("Exception during purge in RollingFileAppender"));

			return false;
		}
	}

	return true;
}

#define RULES_PUT(spec, cls) \
	specs.insert(PatternMap::value_type(LogString(LOG4CXX_STR(spec)), (PatternConstructor) cls ::newInstance))


LOG4CXX_NS::pattern::PatternMap FixedWindowRollingPolicy::getFormatSpecifiers() const
{
	PatternMap specs;
	RULES_PUT("i", IntegerPatternConverter);
	RULES_PUT("index", IntegerPatternConverter);
	return specs;
}
