/*
 * 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/helpers/transcoder.h>
#include <log4cxx/helpers/pool.h>
#include <stdlib.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/private/bytebuffer_priv.h>
#include <log4cxx/helpers/charsetdecoder.h>
#include <log4cxx/helpers/charsetencoder.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/loglog.h>
#include <vector>
#include <cstring>
#if !defined(LOG4CXX)
	#define LOG4CXX 1
#endif
#include <log4cxx/private/log4cxx_private.h>

#if LOG4CXX_CFSTRING_API
	#include <CoreFoundation/CFString.h>
#endif

using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;

void Transcoder::decodeUTF8(const std::string& src, LogString& dst)
{
	std::string::const_iterator iter = src.begin();

	while (iter != src.end())
	{
		auto sv = getCodePoint(src, iter);
		encode(sv, dst);
	}
}

void Transcoder::encodeUTF8(const LogString& src, std::string& dst)
{
#if LOG4CXX_LOGCHAR_IS_UTF8
	dst.append(src);
#else
	LogString::const_iterator iter = src.begin();

	while (iter != src.end())
	{
		unsigned int sv = getCodePoint(src, iter);
		encode(sv, dst);
	}

#endif
}


void Transcoder::encodeUTF8(unsigned int sv, ByteBuffer& dst)
{
	dst.increment_position(CharsetEncoder::putUTF8CodePoint(sv, dst.current()));
}

void Transcoder::encodeUTF16BE(unsigned int sv, ByteBuffer& dst)
{
	dst.increment_position(CharsetEncoder::putUTF16BECodePoint(sv, dst.current()));
}

void Transcoder::encodeUTF16LE(unsigned int sv, ByteBuffer& dst)
{
	dst.increment_position(CharsetEncoder::putUTF16LECodePoint(sv, dst.current()));
}

unsigned int Transcoder::decode(const std::string& src,
	std::string::const_iterator& iter)
{
	auto offset = iter - src.begin();
	auto remaining = src.size() - offset;
	ByteBufferPriv buf(const_cast<char*>(src.data() + offset), remaining);
	auto result = CharsetDecoder::getUTF8CodePoint(buf);
	iter += remaining - buf.remaining();
	return result;
}

	template <typename T>
unsigned int decodeCodePoint(const typename std::basic_string<T>& str, typename std::basic_string<T>::const_iterator& nextCodePoint)
{
	auto lastCodePoint = nextCodePoint;
	auto ch = Transcoder::decode(str, nextCodePoint);
	if (nextCodePoint == lastCodePoint) // failed to decode input?
	{
		// Skip the undecodable run and keep escaping the remaining input
		// instead of discarding it; the run collapses to one replacement.
		for (++nextCodePoint; nextCodePoint != str.end(); ++nextCodePoint)
		{
			auto probe = nextCodePoint;
			Transcoder::decode(str, probe);
			if (probe != nextCodePoint) // next unit starts a decodable sequence
				break;
		}
		ch = 0xFFFD; // The Unicode replacement character
	}
	else if ( (0xD800 <= ch && ch <= 0xDFFF) // UTF-16 surrogate-range
			|| 0xFFFF == ch || 0x10FFFF < ch)
	{
		ch = 0xFFFD; // The Unicode replacement character
	}
	return ch;
}

unsigned int Transcoder::getCodePoint(const std::string& str, std::string::const_iterator& nextCodePoint)
{
	return decodeCodePoint<char>(str, nextCodePoint);
}

void Transcoder::encode(unsigned int sv, std::string& dst)
{
	char tmp[8];
	size_t bytes = CharsetEncoder::putUTF8CodePoint(sv, tmp);
	dst.append(tmp, bytes);
}

/// Does \c str contain the Unicode replacement character
bool Transcoder::hasReplacementCharacter(const std::string& str)
{
	return str.npos != str.find("\xEF\xBF\xBD");
}

void Transcoder::decode(const std::string& src, LogString& dst)
{
#if LOG4CXX_CHARSET_UTF8 && LOG4CXX_LOGCHAR_IS_UTF8
	dst.append(src);
#else
	static CharsetDecoderPtr decoder(CharsetDecoder::getDefaultDecoder());
	dst.reserve(dst.size() + src.size());
	std::string::const_iterator iter = src.begin();
#if !LOG4CXX_CHARSET_EBCDIC

	for (;
		iter != src.end() && ((unsigned char) *iter) < 0x80;
		iter++)
	{
		dst.append(1, *iter);
	}

#endif

	if (iter != src.end())
	{
		size_t offset = iter - src.begin();
		ByteBuffer buf(const_cast<char*>(src.data() + offset), src.size() - offset);

		while (buf.remaining() > 0)
		{
			log4cxx_status_t stat = decoder->decode(buf, dst);

			if (CharsetDecoder::isError(stat))
			{
				encode(LOSSCHAR, dst);
				buf.increment_position(1);
			}
		}

		decoder->decode(buf, dst);
	}

#endif
}



void Transcoder::encode(const LogString& src, std::string& dst)
{
#if LOG4CXX_CHARSET_UTF8 && LOG4CXX_LOGCHAR_IS_UTF8
	dst.append(src);
#else
	static CharsetEncoderPtr encoder(CharsetEncoder::getDefaultEncoder());
	dst.reserve(dst.size() + src.size());
	LogString::const_iterator iter = src.begin();
#if !LOG4CXX_CHARSET_EBCDIC

	for (;
		iter != src.end() && ((unsigned int) *iter) < 0x80;
		iter++)
	{
		dst.append(1, static_cast<char>(*iter));
	}

#endif
	if (iter != src.end())
	{
		static const int BUFSIZE = 256;
		char buf[BUFSIZE];
		ByteBuffer out(buf, BUFSIZE);

		while (iter != src.end())
		{
			log4cxx_status_t stat = encoder->encode(src, iter, out);
			out.flip();
			dst.append(out.data(), out.limit());
			out.clear();

			if (CharsetEncoder::isError(stat))
			{
				encode(LOSSCHAR, dst);
				iter++;
			}
		}

		encoder->encode(src, iter, out);
	}

#endif
}


template<class String, class Iterator>
static unsigned int decodeUTF16(const String& in, Iterator& iter)
{
	unsigned int ch1 = *iter;

	//
	//   if not surrogate pair
	//
	if (ch1 < 0xD800 || ch1 > 0xDFFF)
	{
		//
		//  then advance iterator and return wchar_t value
		//
		if (ch1 != 0xFFFF)
		{
			iter++;
		}

		return ch1;
	}
	else if (ch1 < 0xDC00)
	{
		//
		//  started with high-surrogate value
		//     if there is an additional wchar_t
		Iterator iter2 = iter + 1;

		if (iter2 != in.end())
		{
			unsigned int ch2 = *iter2;

			//
			//    if it is a matching low surrogate then
			//       advance the iterator and return the scalar value
			if (ch2 >= 0xDC00 && ch2 <= 0xDFFF)
			{
				iter += 2;
				return (ch1 - 0xD800) * 0x400 + (ch2 - 0xDC00) + 0x10000;
			}
		}
	}

	//
	//    unrecognized value, do not advance iterator
	//
	return 0xFFFF;
}

template<class String>
static void encodeUTF16(unsigned int sv, String& dst)
{
	if (sv < 0x10000)
	{
		dst.append(1, sv);
	}
	else
	{
		unsigned char u = (unsigned char) (sv >> 16);
		unsigned char w = (unsigned char) (u - 1);
		unsigned short hs = (0xD800 + ((w & 0xF) << 6) + ((sv & 0xFFFF) >> 10));
		unsigned short ls = (0xDC00 + (sv & 0x3FF));
		dst.append(1, hs);
		dst.append(1, ls);
	}
}



#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR || defined(WIN32) || defined(_WIN32)
void Transcoder::decode(const std::wstring& src, LogString& dst)
{
#if LOG4CXX_LOGCHAR_IS_WCHAR
	dst.append(src);
#else
	std::wstring::const_iterator i = src.begin();

	while (i != src.end())
	{
		auto cp = getCodePoint(src, i);
		encode(cp, dst);
	}

#endif
}

void Transcoder::encode(const LogString& src, std::wstring& dst)
{
#if LOG4CXX_LOGCHAR_IS_WCHAR
	dst.append(src);
#else

	for (LogString::const_iterator i = src.begin(); i != src.end();)
	{
		unsigned int cp = getCodePoint(src, i);
		encode(cp, dst);
	}

#endif
}


unsigned int Transcoder::decode(const std::wstring& in,
	std::wstring::const_iterator& iter)
{
#if defined(__STDC_ISO_10646__)
	return *(iter++);
#else
	return decodeUTF16(in, iter);
#endif
}

unsigned int Transcoder::getCodePoint(const std::wstring& str, std::wstring::const_iterator& nextCodePoint)
{
	return decodeCodePoint<wchar_t>(str, nextCodePoint);
}

void Transcoder::encode(unsigned int sv, std::wstring& dst)
{
#if defined(__STDC_ISO_10646__)
	dst.append(1, sv);
#else

	if (sizeof(wchar_t) == 4)
	{
		dst.append(1, sv);
	}
	else
	{
		encodeUTF16(sv, dst);
	}

#endif
}

/// Does \c str contain the Unicode replacement character
bool Transcoder::hasReplacementCharacter(const std::wstring& str)
{
	return str.npos != str.find(LOSSCHAR);
}
#endif

#if LOG4CXX_CFSTRING_API
void Transcoder::decode(const CFStringRef& src, LogString& dst)
{
	auto length = CFStringGetLength(src);
#if defined(_DEBUG)
	if (LogLog::isDebugEnabled())
	{
		LogString msg(LOG4CXX_STR("Transcoder::decodeCFString"));
		msg += LOG4CXX_STR(" length ");
		StringHelper::toString((size_t)length, msg);
		LogLog::debug(msg);
	}
#endif

	if (length > 0)
	{
		std::vector<unsigned short> tmp(length);
		CFStringGetCharacters(src, CFRangeMake(0, length), &tmp[0]);
		for (auto i = tmp.begin(); i != tmp.end(); )
		{
			auto start = i;
			unsigned int cp = decodeUTF16(tmp, i);
			if (cp != 0xFFFF)
			{
				encode(cp, dst);
			}
			else
			{
				encode(LOSSCHAR, dst);
				if (i == start)
				{
					i++;
				}
			}
		}
	}
}

CFStringRef Transcoder::encode(const LogString& src)
{
	std::basic_string<unsigned short> tmp;
	for (auto ch : src)
		encodeUTF16(ch, tmp);
	return CFStringCreateWithCharacters(kCFAllocatorDefault, tmp.data(), tmp.size());
}
#endif // #if LOG4CXX_CFSTRING_API


logchar Transcoder::decode(char val)
{
#if LOG4CXX_CHARSET_EBCDIC
	LogString dst;
	Transcoder::decode(std::string(1, val), dst);
	return dst[0];
#else
	return val;
#endif
}

LogString Transcoder::decode(const char* val)
{
#if LOG4CXX_LOGCHAR_IS_UTF8 && !LOG4CXX_CHARSET_EBCDIC
	return val;
#else
	LogString dst;
	Transcoder::decode(val, dst);
	return dst;
#endif
}


std::string Transcoder::encodeCharsetName(const LogString& val)
{
	char asciiTable[] = { ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
			'@', 'A', 'B', 'C', 'D', 'E', 'F',  'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
			'P', 'Q', 'R', 'S', 'T', 'U', 'V',  'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
			'`', 'a', 'b', 'c', 'd', 'e', 'f',  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
			'p', 'q', 'r', 's', 't', 'u', 'v',  'w', 'x', 'y', 'z', '{', '|', '}', '~'
		};
	std::string out;

	for (auto& item : val)
	{
		if (item >= 0x20 && item < 0x7F)
		{
			out.append(1, asciiTable[item - 0x20]);
		}
		else
		{
			out.append(1, '?');
		}
	}

	return out;
}
