/*
 * 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/helpers/asyncbuffer.h>
#include <log4cxx/helpers/transcoder.h>
#if LOG4CXX_CONCEPTS
#include <variant>
#endif // LOG4CXX_CONCEPTS

namespace LOG4CXX_NS
{

namespace helpers
{

struct AsyncBuffer::Private
{
#if LOG4CXX_CONCEPTS && LOG4CXX_WCHAR_T_API
    using value_t = std::variant<MessageBufferAppender, WideMessageBufferAppender>;
#else // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API)
    using value_t = MessageBufferAppender;
#endif // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API)
	std::vector<value_t> data;

	Private(value_t&& f)
		: data{ std::move(f) }
	{}

#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
	StringViewType fmt_string;
	FmtArgStore    fmt_args;

	Private(const StringViewType& format_string, FmtArgStore&& args)
		: fmt_string{ format_string }
		, fmt_args{ std::move(args) }
	{}

#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
	WideStringViewType fmt_wstring;
	WideFmtArgStore    fmt_wargs;

	Private(const WideStringViewType& format_string, WideFmtArgStore&& args)
		: fmt_wstring{ format_string }
		, fmt_wargs{ std::move(args) }
	{}
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT

};

#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
void AsyncBuffer::initializeForFmt(const StringViewType& format_string, FmtArgStore&& args)
{
	if (!m_priv)
		m_priv = std::make_unique<Private>(format_string, std::move(args));
	else
	{
		m_priv->fmt_string = format_string;
		m_priv->fmt_args = std::move(args);
	}
}

#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
void AsyncBuffer::initializeForFmt(const WideStringViewType& format_string, WideFmtArgStore&& args)
{
	if (!m_priv)
		m_priv = std::make_unique<Private>(format_string, std::move(args));
	else
	{
		m_priv->fmt_wstring = format_string;
		m_priv->fmt_wargs = std::move(args);
	}
}
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT


/** An empty buffer.
*/
AsyncBuffer::AsyncBuffer()
{}

/** A new buffer with the content of \c other
*/
AsyncBuffer::AsyncBuffer(AsyncBuffer&& other)
	: m_priv(std::move(other.m_priv))
{
}

/** Release resources.
*/
AsyncBuffer::~AsyncBuffer()
{
}

/**
* Has no item been added to this?
*/
bool AsyncBuffer::empty() const
{
	bool result{ true };
	if (m_priv)
	{
		result = m_priv->data.empty();
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
		if (result)
			result = (0 == m_priv->fmt_string.size());
#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
		if (result)
			result = (0 == m_priv->fmt_wstring.size());
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
#endif
	}
	return result;
}

/**
* Add text version of buffered values to \c msg
*/
void AsyncBuffer::renderMessage(LogCharMessageBuffer& msg) const
{
	if (m_priv)
	{
		for (auto& renderer : m_priv->data)
#if LOG4CXX_CONCEPTS && LOG4CXX_WCHAR_T_API
		{
#if LOG4CXX_LOGCHAR_IS_UTF8
			if (auto pRenderer = std::get_if<MessageBufferAppender>(&renderer))
				(*pRenderer)(msg);
			else
			{
				WideMessageBuffer wideBuf;
				std::get<WideMessageBufferAppender>(renderer)(wideBuf);
				LOG4CXX_DECODE_WCHAR(lsMsg, wideBuf.extract_str(wideBuf));
				msg << lsMsg;
			}
#else // !LOG4CXX_LOGCHAR_IS_UTF8
			if (auto pRenderer = std::get_if<WideMessageBufferAppender>(&renderer))
				(*pRenderer)(msg);
			else
			{
				CharMessageBuffer narrowBuf;
				std::get<MessageBufferAppender>(renderer)(narrowBuf);
				LOG4CXX_DECODE_CHAR(lsMsg, narrowBuf.extract_str(narrowBuf));
				msg << lsMsg;
			}
#endif // !LOG4CXX_LOGCHAR_IS_UTF8
		}
#else // !LOG4CXX_CONCEPTS
			renderer(msg);
#endif // !LOG4CXX_CONCEPTS

#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
#if LOG4CXX_LOGCHAR_IS_UTF8
		if (0 < m_priv->fmt_string.size())
			msg << fmt::vformat(m_priv->fmt_string, m_priv->fmt_args);
#if LOG4CXX_WCHAR_T_API
		if (0 < m_priv->fmt_wstring.size())
		{
			LOG4CXX_DECODE_WCHAR(lsMsg, fmt::vformat(m_priv->fmt_wstring, m_priv->fmt_wargs));
			msg << lsMsg;
		}
#endif // LOG4CXX_WCHAR_T_API
#endif // LOG4CXX_LOGCHAR_IS_UTF8

#if LOG4CXX_LOGCHAR_IS_WCHAR
		if (0 < m_priv->fmt_wstring.size())
			msg << fmt::vformat(m_priv->fmt_wstring, m_priv->fmt_wargs);
		if (0 < m_priv->fmt_string.size())
		{
			LOG4CXX_DECODE_CHAR(lsMsg, fmt::vformat(m_priv->fmt_string, m_priv->fmt_args));
			msg << lsMsg;
		}
#endif // LOG4CXX_LOGCHAR_IS_WCHAR
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
	}
}

/**
* Remove all message appenders
*/
void AsyncBuffer::clear()
{
	if (m_priv)
	{
		m_priv->data.clear();
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
		m_priv->fmt_string = {};
#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
		m_priv->fmt_wstring = {};
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
	}
}

#if LOG4CXX_CONCEPTS
/**
 *   Append \c function to this buffer.
 */
void AsyncBuffer::append(MessageBufferAppender&& f)
{
	if (!m_priv)
		m_priv = std::make_unique<Private>(std::move(f));
	else
		m_priv->data.push_back(std::move(f));
}

#if LOG4CXX_WCHAR_T_API
/**
 *   Append \c function to this buffer.
 */
void AsyncBuffer::append(WideMessageBufferAppender&& f)
{
	if (!m_priv)
		m_priv = std::make_unique<Private>(std::move(f));
	else
		m_priv->data.push_back(std::move(f));
}
#endif // LOG4CXX_WCHAR_T_API
#else // !LOG4CXX_CONCEPTS
/**
 *   Append \c function to this buffer.
 */
void AsyncBuffer::append(MessageBufferAppender&& f)
{
	if (!m_priv)
		m_priv = std::make_unique<Private>(std::move(f));
	else
		m_priv->data.push_back(std::move(f));
}
#endif // !LOG4CXX_CONCEPTS

} // namespace helpers
} // namespace LOG4CXX_NS

