/*
 * 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(getParent(pool, compressedFile));
		mkdirs(pool, compressedParent);
	}

	if (StringHelper::endsWith(renameTo, LOG4CXX_STR(".gz")))
	{
		renameTo.resize(renameTo.size() - 3);
		GZCompressActionPtr comp = std::make_shared<GZCompressAction>(
					File(renameTo),
					File(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(renameTo),
					File(compressedName),
					true);
		comp->setThrowIOExceptionOnForkFailure(priv->throwIOExceptionOnForkFailure);
		compressAction = comp;
	}

	auto renameAction = std::make_shared<FileRenameAction>(
				File(currentActiveFile),
				File(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(lowFilename);
		File toRenameBase(lowFilename.substr(0, lowFilename.length() - suffixLength));
		File* toRename = &toRenameCompressed;
		bool isBase = false;
		bool found = exists(p, toRenameCompressed);

		if (suffixLength > 0)
		{
			if (found)
			{
				if (exists(p, toRenameBase))
				{
					deleteFile(p, toRenameBase);
				}
			}
			else
			{
				found = exists(p, toRenameBase);
				isBase = true;
			}
		}

		if (found)
		{
			//
			//    if at upper index then
			//        attempt to delete last file
			//        if that fails then abandon purge
			if (i == highIndex)
			{
				if (!deleteFile(p, *toRename))
				{
					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(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;
}
