/*
 * 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/appender.h>
#include <log4cxx/logger.h>
#include <log4cxx/varia/fallbackerrorhandler.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/spi/loggingevent.h>

using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::spi;
using namespace log4cxx::varia;

IMPLEMENT_LOG4CXX_OBJECT(FallbackErrorHandler)

FallbackErrorHandler::FallbackErrorHandler()
	: backup(), primary(), loggers()
{
}

void FallbackErrorHandler::addRef() const
{
	ObjectImpl::addRef();
}

void FallbackErrorHandler::releaseRef() const
{
	ObjectImpl::releaseRef();
}

void FallbackErrorHandler::setLogger(const LoggerPtr& logger)
{
	LogLog::debug(((LogString) LOG4CXX_STR("FB: Adding logger ["))
		+ logger->getName() + LOG4CXX_STR("]."));
	loggers.push_back(logger);
}

void FallbackErrorHandler::error(const LogString& message,
	const std::exception& e,
	int errorCode) const
{
	error(message, e, errorCode, 0);
}

void FallbackErrorHandler::error(const LogString& message,
	const std::exception& e,
	int, const spi::LoggingEventPtr&) const
{
	LogLog::debug(((LogString) LOG4CXX_STR("FB: The following error reported: "))
		+  message, e);
	LogLog::debug(LOG4CXX_STR("FB: INITIATING FALLBACK PROCEDURE."));

	for (size_t i = 0; i < loggers.size(); i++)
	{
		LoggerPtr& l = (LoggerPtr&)loggers.at(i);
		LogLog::debug(((LogString) LOG4CXX_STR("FB: Searching for ["))
			+ primary->getName() + LOG4CXX_STR("] in logger [")
			+ l->getName() + LOG4CXX_STR("]."));
		LogLog::debug(((LogString) LOG4CXX_STR("FB: Replacing ["))
			+ primary->getName() + LOG4CXX_STR("] by [")
			+ backup->getName() + LOG4CXX_STR("] in logger [")
			+ l->getName() + LOG4CXX_STR("]."));
		l->removeAppender(primary);
		LogLog::debug(((LogString) LOG4CXX_STR("FB: Adding appender ["))
			+ backup->getName() + LOG4CXX_STR("] to logger ")
			+ l->getName());
		l->addAppender(backup);
	}
}

void FallbackErrorHandler::setAppender(const AppenderPtr& primary1)
{
	LogLog::debug(((LogString) LOG4CXX_STR("FB: Setting primary appender to ["))
		+ primary1->getName() + LOG4CXX_STR("]."));
	this->primary = primary1;
}

void FallbackErrorHandler::setBackupAppender(const AppenderPtr& backup1)
{
	LogLog::debug(((LogString) LOG4CXX_STR("FB: Setting backup appender to ["))
		+ backup1->getName() + LOG4CXX_STR("]."));
	this->backup = backup1;
}

void FallbackErrorHandler::activateOptions(Pool&)
{
}

void FallbackErrorHandler::setOption(const LogString&, const LogString&)
{
}

