#include "utils.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

utf8_decoder_t *utf8_decoder_create(void) {
    utf8_decoder_t *decoder = (utf8_decoder_t *)malloc(sizeof(utf8_decoder_t));
    if (decoder) {
        decoder->state = 0;
        decoder->remaining = 0;
    }
    return decoder;
}

void utf8_decoder_destroy(utf8_decoder_t *decoder) {
    free(decoder);
}

int utf8_decode_byte(utf8_decoder_t *decoder, unsigned char byte, unsigned int *codepoint) {
    if (!decoder || !codepoint) return -1;
    
    if (decoder->state == 0) {
        if ((byte & 0x80) == 0) {
            *codepoint = byte;
            return 1;
        } else if ((byte & 0xE0) == 0xC0) {
            *codepoint = byte & 0x1F;
            decoder->remaining = 1;
            decoder->state = 1;
            return 0;
        } else if ((byte & 0xF0) == 0xE0) {
            *codepoint = byte & 0x0F;
            decoder->remaining = 2;
            decoder->state = 1;
            return 0;
        } else if ((byte & 0xF8) == 0xF0) {
            *codepoint = byte & 0x07;
            decoder->remaining = 3;
            decoder->state = 1;
            return 0;
        }
    } else if (decoder->state == 1) {
        *codepoint = (*codepoint << 6) | (byte & 0x3F);
        decoder->remaining--;
        if (decoder->remaining == 0) {
            decoder->state = 0;
            return 1;
        }
        return 0;
    }
    
    return -1;
}

void string_trim(char *str) {
    if (!str) return;
    
    char *start = str;
    while (*start && isspace((unsigned char)*start)) start++;
    
    char *end = str + strlen(str) - 1;
    while (end > start && isspace((unsigned char)*end)) end--;
    
    int len = (int)(end - start + 1);
    memmove(str, start, len);
    str[len] = '\0';
}

int string_split(const char *str, char delimiter, char **parts, int max_parts) {
    if (!str || !parts || max_parts <= 0) return 0;
    
    char *copy = malloc(strlen(str) + 1);
    if (!copy) return 0;
    
    strcpy(copy, str);
    int count = 0;
    char *current = copy;
    
    while (current && count < max_parts) {
        char *next = strchr(current, delimiter);
        if (next) *next = '\0';
        
        parts[count] = malloc(strlen(current) + 1);
        if (parts[count]) {
            strcpy(parts[count], current);
            count++;
        }
        
        current = next ? next + 1 : NULL;
    }
    
    free(copy);
    return count;
}

char *string_replace(const char *str, const char *old, const char *new) {
    if (!str || !old || !new) return NULL;
    
    size_t old_len = strlen(old);
    size_t new_len = strlen(new);
    size_t result_size = strlen(str) * 2 + new_len + 1;
    
    char *result = (char *)malloc(result_size);
    if (!result) return NULL;
    
    char *src = (char *)str;
    char *dst = result;
    
    while (*src) {
        if (strncmp(src, old, old_len) == 0) {
            strcpy(dst, new);
            dst += new_len;
            src += old_len;
        } else {
            *dst++ = *src++;
        }
    }
    *dst = '\0';
    
    return result;
}

int strncasecmp(const char *s1, const char *s2, size_t n) {
    if (n == 0) return 0;
    
    for (size_t i = 0; i < n; i++) {
        int c1 = tolower((unsigned char)s1[i]);
        int c2 = tolower((unsigned char)s2[i]);
        if (c1 != c2) return c1 - c2;
        if (c1 == 0) return 0;
    }
    return 0;
}