#include "runtime.h"

#include <string.h>

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#elif defined(__linux__)

#include <uchar.h>
#endif

RT_DLLEXPORT int rtCompareSpanToString(rt_text_span span, const char *cmp) {
    size_t cmp_len = strlen(cmp);
    if (cmp_len != (size_t)span.length)
        return (span.length < cmp_len) ? -1 : 1;
    for (size_t i = 0; i < cmp_len; ++i) {
        if (span.start[i] != cmp[i])
            return span.start[i] - cmp[i];
    }
    return 0;
}

/* These should not be necessary on linux. If we ever run into this problem,
 * they could be implemented pretty easily. */

RT_DLLEXPORT rt_result rtUTF8ToWStr(const char *utf8, wchar_t *wstr, size_t len) {
#ifdef _WIN32
    int res = MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, utf8, -1, wstr, (int)len);
    if (res > 0) {
        return RT_SUCCESS;
    } else {
        DWORD err = GetLastError();
        if (err == ERROR_INSUFFICIENT_BUFFER)
            return RT_INSUFFICIENT_BUFFER;
        else if (err == ERROR_NO_UNICODE_TRANSLATION)
            return RT_INVALID_UNICODE;
        else {
            rtReportError("CORE", "Unexpected error in rtUTF8ToWStr(): %u", err);
            return RT_UNKNOWN_ERROR;
        }
    }
#elif defined(__linux__)
    return RT_UNKNOWN_ERROR;
#endif
}

RT_DLLEXPORT rt_result rtWStrToUTF8(const wchar_t *wstr, char *utf8, size_t len) {
#ifdef _WIN32
    int res = WideCharToMultiByte(CP_UTF8, WC_COMPOSITECHECK, wstr, -1, utf8, (int)len, NULL, NULL);
    if (res > 0) {
        return RT_SUCCESS;
    } else {
        DWORD err = GetLastError();
        if (err == ERROR_INSUFFICIENT_BUFFER)
            return RT_INSUFFICIENT_BUFFER;
        else if (err == ERROR_NO_UNICODE_TRANSLATION)
            return RT_INVALID_UNICODE;
        else {
            rtReportError("CORE", "Unexpected error in rtWStrToUTF8(): %u", err);
            return RT_UNKNOWN_ERROR;
        }
    }
#elif defined(__linux__)
    return RT_UNKNOWN_ERROR;
#endif
}
