#pragma once

struct UTF32Result {
    uint32_t out_str;
    int64_t  advance;
    int64_t  error;
};

struct UTF8Result {
    uint8_t out_str[4];
    int64_t len;
    int64_t error;
};

struct UTF16Result {
    uint16_t out_str[2];
    int64_t  len;
    int64_t  error;
};

struct UTF8Iter {
    char    *data;
    int64_t  len;
    int64_t  utf8_codepoint_byte_size;
    int64_t  i;
    uint32_t item;

    UTF8Iter &operator++() {
        void Advance(UTF8Iter * iter);
        Advance(this);
        return *this;
    }
    friend bool operator!=(const UTF8Iter &a, const UTF8Iter &b) { return a.item != b.item; }
    UTF8Iter   &operator*() { return *this; }
    UTF8Iter    begin() {
        UTF8Iter IterateUTF8Ex(char *data, int64_t len);
        return {IterateUTF8Ex(data, len)};
    }
    UTF8Iter end() { return {}; }
};

API UTF32Result UTF16ToUTF32(uint16_t *c, int64_t max_advance);
API UTF8Result UTF32ToUTF8(uint32_t codepoint);
API UTF32Result UTF8ToUTF32(uint8_t *c, int64_t max_advance);
API UTF16Result UTF32ToUTF16(uint32_t codepoint);

API int64_t CreateCharFromWidechar(char *buffer, int64_t buffer_size, char16_t *in, int64_t inlen);
API int64_t CreateWidecharFromChar(char16_t *buffer, int64_t buffer_size, char *in, int64_t inlen);
API char16_t *ToWidechar(Allocator allocator, String string);
API String16 ToString16(Allocator allocator, String string);
API String ToString(Allocator allocator, String16 string);
API String ToString(Allocator allocator, char16_t *string, int64_t len);
API String ToString(Allocator allocator, char16_t *wstring);

API bool IsValid(UTF8Iter &iter);
API void Advance(UTF8Iter *iter);
API UTF8Iter IterateUTF8Ex(char *data, int64_t len);
API UTF8Iter IterateUTF8(char *data);
API UTF8Iter IterateUTF8(String string);
API bool IsUTF8ContinuationByte(char c);
