#include "common/strutil.h"
#include "common/textModifier.h"

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

static void verify(bool expression, const char* expressionStr, int lineNo) {
    if (expression) {
        return;
    }

    fprintf(stderr, FASTFETCH_TEXT_MODIFIER_ERROR "[%d] %s\n" FASTFETCH_TEXT_MODIFIER_RESET, lineNo, expressionStr);
    exit(1);
}

#define VERIFY(expression) verify((expression), #expression, __LINE__)

int main(void) {
    #if FF_ENABLE_WCWIDTH
    {
        uint8_t width = 255;
        uint8_t bytes = ffUtf8CharLenWidth("", 0, &width);
        VERIFY(bytes == 0);
        VERIFY(width == 0);
    }

    {
        uint8_t width = 0;
        uint8_t bytes = ffUtf8CharLenWidth("A", 1, &width);
        VERIFY(bytes == 1);
        VERIFY(width == 1);
    }

    {
        const char* ch = "\xE6\x96\x87"; // 文 U+6587
        uint8_t width = 0;
        uint8_t bytes = ffUtf8CharLenWidth(ch, 3, &width);
        VERIFY(bytes == 3);
        VERIFY(width == 2);
    }

    {
        const char* combining = "\xCC\x81"; // ◌́ U+0301
        uint8_t width = 0;
        uint8_t bytes = ffUtf8CharLenWidth(combining, 2, &width);
        VERIFY(bytes == 2);
        VERIFY(width == 0); // Should be 1 since there's no base character
    }

    {
        uint8_t width = 0;
        uint8_t bytes = ffUtf8CharLenWidth("\xE6\x96\x87", 1, &width); // truncated
        VERIFY(bytes == 1);
        VERIFY(width == 1);
    }

    {
        uint8_t width = 0;
        uint8_t bytes = ffUtf8CharLenWidth("\xE6"
                                           "A",
            2,
            &width); // invalid continuation
        VERIFY(bytes == 1);
        VERIFY(width == 1);
    }

    {
        VERIFY(ffUtf8StrWidth("abc", 3) == 3);
    }

    {
        const char* mixed = "A"
                            "\xE6\x96\x87" // 文 U+6587
                            "B";
        VERIFY(ffUtf8StrWidth(mixed, 5) == 4);
    }

    {
        const char* combining = "A\xCC\x81"; // Á
        VERIFY(ffUtf8StrWidth(combining, 3) == 1);
    }

    {
        VERIFY(ffUtf8StrWidth("\xE6"
                              "A",
                   2) == 2);
    }

    {
        VERIFY(ffUtf8StrWidth("", 0) == 0);
        VERIFY(ffUtf8StrWidth("A\0B", 3) == 1);
    }

    {
        const char* emoji = "\xF0\x9F\x98\x80"; // U+1F600 😀
        uint8_t width = 0;
        uint8_t bytes = ffUtf8CharLenWidth(emoji, 4, &width);
        VERIFY(bytes == 4);
        VERIFY(width == 2);
    }

    puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
    #else
    puts("\033[33mTests skipped because wcwidth support is disabled." FASTFETCH_TEXT_MODIFIER_RESET);
    #endif
    return 0;
}
