#include "util.h"
#include <windows.h>


namespace util {

    const wchar_t* convertAnsiToUtf16(const char* ansi) {
        int ansiSize = (int)strlen(ansi);
        int utf16Size = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansi, ansiSize + 1, NULL, 0);
        wchar_t* utf16 = new wchar_t[utf16Size];
        MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansi, ansiSize + 1, &utf16[0], utf16Size);
        return utf16;
    }

    const wchar_t* convertUtf8ToUtf16(const char* utf8) {
        int utf8Size = (int)strlen(utf8);
        int utf16Size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, utf8Size + 1, NULL, 0);
        wchar_t* utf16 = new wchar_t[utf16Size];
        MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, utf8Size + 1, &utf16[0], utf16Size);
        return utf16;
    }

    const char* convertUtf16ToUtf8(const wchar_t* utf16) {
        int utf16Size = (int)wcslen(utf16);
        int utf8Size = ::WideCharToMultiByte(CP_UTF8, 0, utf16, utf16Size + 1, NULL, 0, NULL, NULL);
        char* utf8 = new char[utf8Size]; 
	    WideCharToMultiByte(CP_UTF8, 0, utf16, utf16Size + 1, &utf8[0], utf8Size, NULL, NULL);	
        return utf8;
    }

    errno_t FileStream::open(const wchar_t* filename, const wchar_t* mode) 
    {
        return _wfopen_s(&_file, filename, mode);
    }

    void FileStream::close()
    {
        fclose(_file);
    }

    bool isOneOf(const wchar_t item, const wchar_t* set) {
        const wchar_t* ptr = set;

        while (*ptr != NULL) {
            if (item == *ptr)
                return true;

            ptr++;
        }

        return false;
    }

    std::wstring reverse(const std::wstring& str) {
        std::wstring rstr = L"";

        for (std::wstring::const_reverse_iterator iChar = str.rbegin(); iChar != str.rend(); ++iChar) {
            rstr += *iChar;
        }

        return rstr;
    }

    std::wstring trim_left(const std::wstring& str, const wchar_t* trimchars) {
        size_t i = 0;

        while ((i < str.length()) && isOneOf(str[i], trimchars)) {
            i++;
        }
        
        if (i != str.length())
            return str.substr(i);

        else
            return L"";
    }

    std::wstring trim_right(const std::wstring& str, const wchar_t* trimchars) {
        std::wstring rstr = reverse(str);

        size_t i = 0;
        while ((i < rstr.length()) && isOneOf(rstr[i], trimchars)) {
            i++;
        }
        
        if (i != rstr.length())
            return reverse(rstr.substr(i));

        else
            return L"";
    }


    std::wstring trim(const std::wstring& str, const wchar_t* trimchars) {
        return trim_right(trim_left(str, trimchars), trimchars);
    }

};