#include "strconv.h"

namespace StrConv
{
std::wstring AnsiToUnicode(const char *src)
{
    if (src == NULL || src[0] == '\0')
    {
        return L"";
    }
    std::string strSrc(src);
    int length = MultiByteToWideChar(CP_ACP, 0, strSrc.c_str(), -1, NULL, 0);
    wchar_t *buf = new wchar_t[length + 1];
    MultiByteToWideChar(CP_ACP, 0, strSrc.c_str(), -1, buf, length);
    buf[length] = L'\0';
    std::wstring dest = buf;
    delete [] buf;
    return dest;
}

std::string AnsiToUTF8(const char *src)
{
    std::wstring unicode = AnsiToUnicode(src);
    return StrConv::UnicodeToUTF8(unicode.c_str());
}

std::string UTF8ToAnsi(const char *src)
{
    static std::wstring unicode = StrConv::UTF8ToUnicode(src);
    return StrConv::UnicodeTochar(unicode.c_str());
}

std::wstring UTF8ToUnicode(const char *src)
{
    if (src == NULL || src[0] == '\0')
    {
        return L"";
    }
    std::string strSrc(src);
    int length = MultiByteToWideChar(CP_UTF8, 0, strSrc.c_str(), -1, NULL, 0);
    wchar_t *buf = new wchar_t[length + 1];
    MultiByteToWideChar(CP_UTF8, 0, strSrc.c_str(), -1, buf, length);
    buf[length] = L'\0';
    std::wstring dest = buf;
    delete [] buf;
    return dest;
}

std::string UnicodeToUTF8(const wchar_t *src)
{
    if (src == NULL || src[0] == '\0')
    {
        return "";
    }
    std::wstring strSrc(src);
    int length = WideCharToMultiByte(CP_UTF8, 0, strSrc.c_str(),
                                     -1, NULL, 0, NULL, FALSE);
    char *buf = new char[length + 1];
    WideCharToMultiByte(CP_UTF8, 0, strSrc.c_str(), -1, buf, length, NULL, FALSE);
    buf[length] = '\0';
    std::string dest = buf;
    delete [] buf;
    return dest;
}

//std::string UTF8ToNative(const char *src)
//{
//#ifdef UNICODE
//    return UTF8ToUnicode(src);
//#else
//    return UTF8ToAnsi(src);
//#endif
//}

std::string NativeToUTF8(LPCTSTR src)
{
#ifdef UNICODE
    return UnicodeToUTF8(src);
#else
    return AnsiToUTF8(src);
#endif
}

std::wstring TCHARToUnicode(LPCTSTR src)
{
    if (src == NULL || src[0] == '\0')
    {
        return L"";
    }
#ifdef UNICODE
    return src;
#else
    return AnsiToUnicode(src);
#endif
}

std::string UnicodeTochar(const wchar_t *src)
{
    if (!src)
        return "";

    int unicode_len = wcslen(src);
    int charcount = ::WideCharToMultiByte(CP_ACP, 0, src, unicode_len, NULL, 0, NULL, NULL);
    if (charcount == 0)
        return "";

    std::string mb;
    mb.resize(charcount);
    ::WideCharToMultiByte(CP_ACP, 0, src, unicode_len, &mb[0], charcount, NULL, NULL);

    return mb;
}

bool UTF8ToUnicode(std::wstring &str_out, const std::string &str_in)
{
    int  len = str_in.length();
    int  unicodeLen = MultiByteToWideChar( CP_UTF8,
                                         0,
                                         str_in.c_str(),
                                         -1,
                                         NULL,
                                         0 );
    if (unicodeLen <= 0){
        return false;
    }

    wchar_t*  pUnicode = new  wchar_t[unicodeLen+1];
    memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));


    int ret = MultiByteToWideChar( CP_UTF8,
                                  0,
                                  str_in.c_str(),
                                  -1,
                                  (LPWSTR)pUnicode,
                                  unicodeLen );
    if (ret <= 0){
        delete[] pUnicode;
        return false;
    }

    str_out = ( wchar_t* )pUnicode;
    delete[]  pUnicode;

    return  true;
}

bool UnicodeToUTF8(std::string &str_out, const std::wstring &str_in)
{
    char* pElementText;
    int  iTextLen;

    iTextLen = WideCharToMultiByte( CP_UTF8,
                                   0,
                                   str_in.c_str(),
                                   -1,
                                   NULL,
                                   0,
                                   NULL,
                                   NULL );
    if (iTextLen <=0 ){
        return false;
    }

    pElementText = new char[iTextLen + 1];
    memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
    int ret = WideCharToMultiByte( CP_UTF8,
                                  0,
                                  str_in.c_str(),
                                  -1,
                                  pElementText,
                                  iTextLen,
                                  NULL,
                                  NULL );


    if (ret <= 0){
        delete[] pElementText;
        return false;
    }

    str_out= pElementText;
    delete[] pElementText;
    return true;
}

bool UnicodeToMulti(std::string &str_out, const std::wstring &str_in)
{
    char* pElementText;
    int  iTextLen;

    iTextLen = WideCharToMultiByte( CP_ACP,
                                   0,
                                   str_in.c_str(),
                                   -1,
                                   NULL,
                                   0,
                                   NULL,
                                   NULL );
    if (iTextLen <=0 ){
        return false;
    }

    pElementText = new char[iTextLen + 1];
    memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
    int ret = WideCharToMultiByte( CP_ACP,
                                  0,
                                  str_in.c_str(),
                                  -1,
                                  pElementText,
                                  iTextLen,
                                  NULL,
                                  NULL );


    if (ret <= 0){
        delete[] pElementText;
        return false;
    }

    str_out= pElementText;
    delete[] pElementText;
    return true;
}

bool MultiToUnicode(std::wstring &str_out, const std::string &str_in)
{
    int  len = str_in.length();
    int  unicodeLen = MultiByteToWideChar( CP_ACP,
                                         0,
                                         str_in.c_str(),
                                         -1,
                                         NULL,
                                         0 );
    if (unicodeLen <= 0){
        return false;
    }

    wchar_t*  pUnicode = new  wchar_t[unicodeLen+1];
    memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));

    int ret = MultiByteToWideChar( CP_ACP,
                                  0,
                                  str_in.c_str(),
                                  -1,
                                  (LPWSTR)pUnicode,
                                  unicodeLen );
    if (ret <= 0){
        delete[] pUnicode;
        return false;
    }

    str_out = ( wchar_t* )pUnicode;
    delete[]  pUnicode;

    return  true;
}

};



