/*
 * 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>
#include <log4cxx/private/appenderskeleton_priv.h>
#include <log4cxx/private/writerappender_priv.h>

using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;

struct ConsoleAppender::ConsoleAppenderPriv : public WriterAppender::WriterAppenderPriv
{
	ConsoleAppenderPriv(LogString target) :
		WriterAppenderPriv(),
		target(target) {}

	LogString target;
};

#define _priv static_cast<ConsoleAppenderPriv*>(m_priv.get())

IMPLEMENT_LOG4CXX_OBJECT(ConsoleAppender)

ConsoleAppender::ConsoleAppender()
	: WriterAppender (std::make_unique<ConsoleAppenderPriv>(getSystemOut()))
{
}

ConsoleAppender::ConsoleAppender(const LayoutPtr& layout)
	: WriterAppender (std::make_unique<ConsoleAppenderPriv>(getSystemOut()))
{
	setLayout(layout);
	_priv->setWriter(std::make_shared<SystemOutWriter>());
	_priv->activateOptions();
}

ConsoleAppender::ConsoleAppender(const LayoutPtr& layout, const LogString& target)
	: WriterAppender (std::make_unique<ConsoleAppenderPriv>(target))
{
	setLayout(layout);
	setTarget(target);
	ConsoleAppender::activateOptions();
}

ConsoleAppender::~ConsoleAppender()
{
}

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

const LogString& ConsoleAppender::getSystemErr()
{
	static const WideLife<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")))
	{
		_priv->target = getSystemOut();
	}
	else if (StringHelper::equalsIgnoreCase(v,
			LOG4CXX_STR("SYSTEM.ERR"), LOG4CXX_STR("system.err")))
	{
		_priv->target = getSystemErr();
	}
	else
	{
		targetWarn(value);
	}
}

LogString ConsoleAppender::getTarget() const
{
	return _priv->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(  )
{
	if (StringHelper::equalsIgnoreCase(_priv->target,
			LOG4CXX_STR("SYSTEM.OUT"), LOG4CXX_STR("system.out")))
	{
		_priv->setWriter(std::make_shared<SystemOutWriter>());
	}
	else if (StringHelper::equalsIgnoreCase(_priv->target,
			LOG4CXX_STR("SYSTEM.ERR"), LOG4CXX_STR("system.err")))
	{
		_priv->setWriter(std::make_shared<SystemErrWriter>());
	}

	_priv->activateOptions();
}

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);
	}
}






