/*
 * 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/stream.h>
#include <log4cxx/helpers/transcoder.h>
#if !defined(LOG4CXX)
	#define LOG4CXX 1
#endif
#include <log4cxx/private/log4cxx_private.h>

using namespace log4cxx;

logstream_base::logstream_ios_base::logstream_ios_base(std::ios_base::fmtflags initval,
	int initsize)
{
#if LOG4CXX_MEMSET_IOS_BASE
	//
	//    the destructor for std::ios_base in the MSVC STL
	//        releases a pointer that was not initialized in the constructor.
	//
	memset(this, 0, sizeof(*this));
#endif
#if LOG4CXX_INIT_IOS_BASE
	init(NULL);
#endif
	flags(initval);
	precision(initsize);
	width(initsize);

}


logstream_base::logstream_base(const LoggerPtr& log,
	const LevelPtr& lvl) : initset((std::ios_base::fmtflags) - 1, 1),
	initclear((std::ios_base::fmtflags) 0, 0), fillchar(0), fillset(false), logger(log), level(lvl), location()
{
	enabled = logger->isEnabledFor(level);
}

logstream_base::~logstream_base()
{
}

void logstream_base::insert(std::ios_base & (*manip)(std::ios_base&))
{
	get_stream_state(initclear, initset, fillchar, fillset);
	(*manip)(initset);
	(*manip)(initclear);
	refresh_stream_state();
}

bool logstream_base::set_stream_state(std::ios_base& dest, int& dstchar)
{
	std::ios_base::fmtflags setval = initset.flags();
	std::ios_base::fmtflags clrval = initclear.flags();
	std::ios_base::fmtflags mask = setval ^ (~clrval);
	dest.setf(clrval, mask);

	if (initset.precision() == initclear.precision())
	{
		dest.precision(initset.precision());
	}

	if (initset.width() == initclear.width())
	{
		dest.width(initset.width());
	}

	dstchar = fillchar;
	return fillset;
}

logstream_base& logstream_base::endmsg(logstream_base& stream)
{
	stream.end_message();
	return stream;
}

logstream_base& logstream_base::nop(logstream_base& stream)
{
	return stream;
}

void logstream_base::end_message()
{
	if (isEnabled())
	{
		log(logger, level, location);
	}

	erase();
}



int log4cxx::logstream_base::precision(int p)
{
	get_stream_state(initclear, initset, fillchar, fillset);
	initset.precision(p);
	int oldVal = (int)initclear.precision(p);
	refresh_stream_state();
	return oldVal;
}

int log4cxx::logstream_base::precision()
{
	get_stream_state(initclear, initset, fillchar, fillset);
	return (int)initclear.precision();
}

int log4cxx::logstream_base::width(int w)
{
	get_stream_state(initclear, initset, fillchar, fillset);
	initset.width(w);
	int oldVal = (int)initclear.width(w);
	refresh_stream_state();
	return oldVal;
}

int log4cxx::logstream_base::width()
{
	get_stream_state(initclear, initset, fillchar, fillset);
	return (int)initclear.width();
}

int log4cxx::logstream_base::fill(int newfill)
{
	get_stream_state(initclear, initset, fillchar, fillset);
	int oldfill = fillchar;
	fillchar = newfill;
	fillset = true;
	refresh_stream_state();
	return oldfill;
}

int logstream_base::fill()
{
	get_stream_state(initclear, initset, fillchar, fillset);
	return fillchar;
}

std::ios_base::fmtflags logstream_base::flags(std::ios_base::fmtflags newflags)
{
	get_stream_state(initclear, initset, fillchar, fillset);
	initset.flags(newflags);
	std::ios_base::fmtflags oldVal = initclear.flags(newflags);
	refresh_stream_state();
	return oldVal;
}

std::ios_base::fmtflags logstream_base::setf(std::ios_base::fmtflags newflags, std::ios_base::fmtflags mask)
{
	get_stream_state(initclear, initset, fillchar, fillset);
	initset.setf(newflags, mask);
	std::ios_base::fmtflags oldVal = initclear.setf(newflags, mask);
	refresh_stream_state();
	return oldVal;
}

std::ios_base::fmtflags logstream_base::setf(std::ios_base::fmtflags newflags)
{
	get_stream_state(initclear, initset, fillchar, fillset);
	initset.setf(newflags);
	std::ios_base::fmtflags oldVal = initclear.setf(newflags);
	refresh_stream_state();
	return oldVal;
}



void logstream_base::setLevel(const ::log4cxx::LevelPtr& newlevel)
{
	level = newlevel;
	bool oldLevel = enabled;
	enabled = logger->isEnabledFor(level);

	if (oldLevel != enabled)
	{
		erase();
	}
}

bool logstream_base::isEnabledFor(const ::log4cxx::LevelPtr& l) const
{
	return logger->isEnabledFor(l);
}


void logstream_base::setLocation(const log4cxx::spi::LocationInfo& newlocation)
{
	if (LOG4CXX_UNLIKELY(enabled))
	{
		location = newlocation;
	}
}


logstream::logstream(const log4cxx::LoggerPtr& logger,
	const log4cxx::LevelPtr& level) : logstream_base(logger, level), stream(0)
{
}

logstream::logstream(const Ch* loggerName,
	const log4cxx::LevelPtr& level)
	: logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0)
{
}


logstream::logstream(const std::basic_string<Ch>& loggerName,
	const log4cxx::LevelPtr& level) : logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0)
{
}

logstream::~logstream()
{
	delete stream;
}

logstream& logstream::operator<<(logstream_base & (*manip)(logstream_base&))
{
	(*manip)(*this);
	return *this;
}

logstream& logstream::operator<<(const LevelPtr& l)
{
	setLevel(l);
	return *this;
}

logstream& logstream::operator<<(const log4cxx::spi::LocationInfo& newlocation)
{
	setLocation(newlocation);
	return *this;
}

logstream& logstream::operator>>(const log4cxx::spi::LocationInfo& newlocation)
{
	setLocation(newlocation);
	return *this;
}

logstream& logstream::operator<<(std::ios_base & (*manip)(std::ios_base&))
{
	logstream_base::insert(manip);
	return *this;
}

logstream::operator std::basic_ostream<char>& ()
{
	if (stream == 0)
	{
		stream = new std::basic_stringstream<Ch>();
		refresh_stream_state();
	}

	return *stream;
}

void logstream::log(LoggerPtr& log,
	const LevelPtr& lev,
	const log4cxx::spi::LocationInfo& loc)
{
	if (stream != 0)
	{
		std::basic_string<Ch> msg = stream->str();

		if (!msg.empty())
		{
			log->log(lev, msg, loc);
		}
	}
}


void logstream::erase()
{
	if (stream != 0)
	{
		std::basic_string<Ch> emptyStr;
		stream->str(emptyStr);
	}
}


void logstream::get_stream_state(std::ios_base& base,
	std::ios_base& mask,
	int& fill,
	bool& fillSet) const
{
	if (stream != 0)
	{
		std::ios_base::fmtflags flags = stream->flags();
		base.flags(flags);
		mask.flags(flags);
		int width = (int)stream->width();
		base.width(width);
		mask.width(width);
		int precision = (int)stream->precision();
		base.precision(precision);
		mask.precision(precision);
		fill = stream->fill();
		fillSet = true;
	}
}

void logstream::refresh_stream_state()
{
	if (stream != 0)
	{
		int ch;

		if (logstream_base::set_stream_state(*stream, ch))
		{
			stream->fill(ch);
		}
	}
}


#if LOG4CXX_WCHAR_T_API

wlogstream::wlogstream(const log4cxx::LoggerPtr& logger,
	const log4cxx::LevelPtr& level) : logstream_base(logger, level), stream(0)
{
}

wlogstream::wlogstream(const Ch* loggerName,
	const log4cxx::LevelPtr& level)
	: logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0)
{
}


wlogstream::wlogstream(const std::basic_string<Ch>& loggerName,
	const log4cxx::LevelPtr& level) : logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0)
{
}

wlogstream::~wlogstream()
{
	delete stream;
}

wlogstream& wlogstream::operator<<(logstream_base & (*manip)(logstream_base&))
{
	(*manip)(*this);
	return *this;
}

wlogstream& wlogstream::operator<<(const LevelPtr& l)
{
	setLevel(l);
	return *this;
}

wlogstream& wlogstream::operator<<(const log4cxx::spi::LocationInfo& newlocation)
{
	setLocation(newlocation);
	return *this;
}

wlogstream& wlogstream::operator>>(const log4cxx::spi::LocationInfo& newlocation)
{
	setLocation(newlocation);
	return *this;
}




wlogstream& wlogstream::operator<<(std::ios_base & (*manip)(std::ios_base&))
{
	logstream_base::insert(manip);
	return *this;
}

wlogstream::operator std::basic_ostream<wchar_t>& ()
{
	if (stream == 0)
	{
		stream = new std::basic_stringstream<Ch>();
		refresh_stream_state();
	}

	return *stream;
}

void wlogstream::log(LoggerPtr& log,
	const LevelPtr& lev,
	const log4cxx::spi::LocationInfo& loc)
{
	if (stream != 0)
	{
		std::basic_string<Ch> msg = stream->str();

		if (!msg.empty())
		{
			log->log(lev, msg, loc);
		}
	}
}


void wlogstream::erase()
{
	if (stream != 0)
	{
		std::basic_string<Ch> emptyStr;
		stream->str(emptyStr);
	}
}


void wlogstream::get_stream_state(std::ios_base& base,
	std::ios_base& mask,
	int& fill,
	bool& fillSet) const
{
	if (stream != 0)
	{
		std::ios_base::fmtflags flags = stream->flags();
		base.flags(flags);
		mask.flags(flags);
		int width = (int)stream->width();
		base.width(width);
		mask.width(width);
		int precision = (int)stream->precision();
		base.precision(precision);
		mask.precision(precision);
		fill = stream->fill();
		fillSet = true;
	}
}

void wlogstream::refresh_stream_state()
{
	if (stream != 0)
	{
		int ch;

		if (logstream_base::set_stream_state(*stream, ch))
		{
			stream->fill(ch);
		}
	}
}
#endif

#if LOG4CXX_UNICHAR_API
ulogstream::ulogstream(const Ch* loggerName,
	const log4cxx::LevelPtr& level)
	: logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0)
{
}


ulogstream::ulogstream(const std::basic_string<Ch>& loggerName,
	const log4cxx::LevelPtr& level) : logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0)
{
}
#endif

#if LOG4CXX_CFSTRING_API
ulogstream::ulogstream(const CFStringRef& loggerName,
	const log4cxx::LevelPtr& level)
	: logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0)
{
}

#endif


#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API

ulogstream::ulogstream(const log4cxx::LoggerPtr& logger,
	const log4cxx::LevelPtr& level) : logstream_base(logger, level), stream(0)
{
}



ulogstream::~ulogstream()
{
	delete stream;
}

ulogstream& ulogstream::operator<<(logstream_base & (*manip)(logstream_base&))
{
	(*manip)(*this);
	return *this;
}

ulogstream& ulogstream::operator<<(const LevelPtr& level)
{
	setLevel(level);
	return *this;
}

ulogstream& ulogstream::operator<<(const log4cxx::spi::LocationInfo& newlocation)
{
	setLocation(newlocation);
	return *this;
}

ulogstream& ulogstream::operator>>(const log4cxx::spi::LocationInfo& newlocation)
{
	setLocation(newlocation);
	return *this;
}




ulogstream& ulogstream::operator<<(std::ios_base & (*manip)(std::ios_base&))
{
	logstream_base::insert(manip);
	return *this;
}

ulogstream::operator std::basic_ostream<UniChar>& ()
{
	if (stream == 0)
	{
		stream = new std::basic_stringstream<Ch>();
		refresh_stream_state();
	}

	return *stream;
}

void ulogstream::log(LoggerPtr& logger,
	const LevelPtr& level,
	const log4cxx::spi::LocationInfo& location)
{
	if (stream != 0)
	{
		std::basic_string<Ch> msg = stream->str();

		if (!msg.empty() && logger->isEnabledFor(level))
		{
			LOG4CXX_DECODE_UNICHAR(lsmsg, msg);
			logger->forcedLogLS(level, lsmsg, location);
		}
	}
}


void ulogstream::erase()
{
	if (stream != 0)
	{
		std::basic_string<Ch> emptyStr;
		stream->str(emptyStr);
	}
}


void ulogstream::get_stream_state(std::ios_base& base,
	std::ios_base& mask,
	int& fill,
	bool& fillSet) const
{
	if (stream != 0)
	{
		std::ios_base::fmtflags flags = stream->flags();
		base.flags(flags);
		mask.flags(flags);
		int width = stream->width();
		base.width(width);
		mask.width(width);
		int precision = stream->precision();
		base.precision(precision);
		mask.precision(precision);
		fill = stream->fill();
		fillSet = true;
	}
}

void ulogstream::refresh_stream_state()
{
	if (stream != 0)
	{
		int fillchar;

		if (logstream_base::set_stream_state(*stream, fillchar))
		{
			stream->fill(fillchar);
		}
	}
}
#endif


