#pragma once

#include <windows.h>
#include <cstdlib>
#include <vector>
#include <string>


namespace util
{
namespace string
{


//! ワイド文字列からマルチバイト文字列
//! ロケール依存
inline void ToMultiByte(const std::wstring &src, std::string &dst)
{
	if( src.empty() )
		return;

	std::vector< char > mbs( src.length() * MB_CUR_MAX + 1 );

	wcstombs(&mbs[0], src.c_str(), src.length() * MB_CUR_MAX + 1);
	dst = &mbs[0];
}

//! ワイド文字列からマルチバイト文字列
//! ロケール依存
inline std::string ToMultiByte(const std::wstring &src)
{
	std::string dst;
	ToMultiByte( src , dst );
	return dst;
}


//! マルチバイト文字列からワイド文字列
//! ロケール依存
inline void ToUnicode(const std::string &src, std::wstring &dst)
{
	if( src.empty() )
		return;

	std::vector< wchar_t > wcs( src.length() + 1 );
	mbstowcs(&wcs[0], src.c_str(), src.length() + 1);
	dst = &wcs[0];
}

//! マルチバイト文字列からワイド文字列
//! ロケール依存
inline std::wstring ToUnicode(const std::string &src)
{
	std::wstring dst;
	ToUnicode( src , dst );
	return dst;
}


inline void SJIStoUTF8(const char* sjis, std::vector<char>& utf8)
{
	utf8.clear();

	// Convert SJIS -> UTF-16
	const int nSize = ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)sjis, -1, NULL, 0 );
	if(nSize == 0)
		return;

	std::vector<char> buffUtf16(nSize * 2 + 2);
	::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)sjis, -1, (LPWSTR)&buffUtf16[0], nSize );

	// Convert UTF-16 -> UTF-8
	const int nSizeUtf8 = ::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)&buffUtf16[0], -1, NULL, 0, NULL, NULL );

	if(nSizeUtf8 == 0)
		return;

	std::vector<char> buffUtf8(nSizeUtf8 * 2, 0);
	::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)&buffUtf16[0], -1, (LPSTR)&buffUtf8[0], nSizeUtf8, NULL, NULL );

	// Peform convert
	utf8.resize(nSizeUtf8, 0);

	memcpy( &utf8[0], &buffUtf8[0], nSizeUtf8 );
}


inline void UTF8toSJIS(const char* utf8, std::string& sjis)
{
	sjis.clear();

	//UTF-8からUTF-16へ変換
	const int nn = ::MultiByteToWideChar( CP_UTF8, 0, (LPCSTR)utf8, -1, NULL, 0 );
	if(nn == 0)
		return;

	std::vector<char> buffUtf16(nn * 2 + 2);
	::MultiByteToWideChar( CP_UTF8, 0, (LPCSTR)utf8, -1, (LPWSTR)&buffUtf16[0], nn );

	//UTF-16からShift-JISへ変換
	const int nSizeSJis = ::WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)&buffUtf16[0], -1, NULL, 0, NULL, NULL );
	if(nSizeSJis == 0)
		return;

	std::vector<char> buffSJis(nSizeSJis * 2, 0);
	::WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)&buffUtf16[0], -1, (LPSTR)&buffSJis[0], nSizeSJis, NULL, NULL );

	sjis = &buffSJis[0];
}


}
}
