/*
 * 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/consoleappender.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/systemoutwriter.h>
#include <log4cxx/helpers/systemerrwriter.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/layout.h>

using namespace log4cxx;
using namespace log4cxx::helpers;

IMPLEMENT_LOG4CXX_OBJECT(ConsoleAppender)

ConsoleAppender::ConsoleAppender()
	: target(getSystemOut())
{
}

ConsoleAppender::ConsoleAppender(const LayoutPtr& layout1)
	: target(getSystemOut())
{
	setLayout(layout1);
	Pool p;
	WriterPtr writer1(new SystemOutWriter());
	setWriter(writer1);
	WriterAppender::activateOptions(p);
}

ConsoleAppender::ConsoleAppender(const LayoutPtr& layout1, const LogString& target1)
	: target(target1)
{
	setLayout(layout1);
	Pool p;
	ConsoleAppender::activateOptions(p);
}

ConsoleAppender::~ConsoleAppender()
{
	finalize();
}

const LogString& ConsoleAppender::getSystemOut()
{
	static const LogString name(LOG4CXX_STR("System.out"));
	return name;
}

const LogString& ConsoleAppender::getSystemErr()
{
	static const LogString name(LOG4CXX_STR("System.err"));
	return name;
}

void ConsoleAppender::setTarget(const LogString& value)
{
	LogString v = StringHelper::trim(value);

	if (StringHelper::equalsIgnoreCase(v,
			LOG4CXX_STR("SYSTEM.OUT"), LOG4CXX_STR("system.out")))
	{
		target = getSystemOut();
	}
	else if (StringHelper::equalsIgnoreCase(v,
			LOG4CXX_STR("SYSTEM.ERR"), LOG4CXX_STR("system.err")))
	{
		target = getSystemErr();
	}
	else
	{
		targetWarn(value);
	}
}

LogString ConsoleAppender::getTarget() const
{
	return target;
}

void ConsoleAppender::targetWarn(const LogString& val)
{
	LogLog::warn(((LogString) LOG4CXX_STR("["))
		+ val +  LOG4CXX_STR("] should be system.out or system.err."));
	LogLog::warn(LOG4CXX_STR("Using previously set target, System.out by default."));
}

void ConsoleAppender::activateOptions(Pool& p)
{
	if (StringHelper::equalsIgnoreCase(target,
			LOG4CXX_STR("SYSTEM.OUT"), LOG4CXX_STR("system.out")))
	{
		WriterPtr writer1(new SystemOutWriter());
		setWriter(writer1);
	}
	else if (StringHelper::equalsIgnoreCase(target,
			LOG4CXX_STR("SYSTEM.ERR"), LOG4CXX_STR("system.err")))
	{
		WriterPtr writer1(new SystemErrWriter());
		setWriter(writer1);
	}

	WriterAppender::activateOptions(p);
}

void ConsoleAppender::setOption(const LogString& option, const LogString& value)
{
	if (StringHelper::equalsIgnoreCase(option,
			LOG4CXX_STR("TARGET"), LOG4CXX_STR("target")))
	{
		setTarget(value);
	}
	else
	{
		WriterAppender::setOption(option, value);
	}
}






