#include "form.h"

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

static char *form_strdup(const char *s) {
    size_t len = strlen(s);
    char *copy = malloc(len + 1);
    if (copy == NULL) {
        return NULL;
    }
    memcpy(copy, s, len + 1);
    return copy;
}

void form_url_decode(char *s) {
    char *src = s;
    char *dst = s;

    while (*src != '\0') {
        if (*src == '+') {
            *dst++ = ' ';
            src++;
        } else if (
            src[0] == '%' &&
            isxdigit((unsigned char)src[1]) &&
            isxdigit((unsigned char)src[2])
        ) {
            char hex[3] = { src[1], src[2], '\0' };
            *dst++ = (char)strtol(hex, NULL, 16);
            src += 3;
        } else {
            *dst++ = *src++;
        }
    }

    *dst = '\0';
}

int form_parse(char *input, FormItem *items, int max_items) {
    int count = 0;
    char *pair = strtok(input, "&");

    while (pair != NULL && count < max_items) {
        char *equal = strchr(pair, '=');
        if (equal != NULL) {
            *equal = '\0';
            items[count].key = form_strdup(pair);
            items[count].value = form_strdup(equal + 1);
            if (items[count].key == NULL || items[count].value == NULL) {
                free(items[count].key);
                free(items[count].value);
                break;
            }
            form_url_decode(items[count].key);
            form_url_decode(items[count].value);
            count++;
        }
        pair = strtok(NULL, "&");
    }

    return count;
}

const char *form_get(FormItem *items, int count, const char *key) {
    for (int i = 0; i < count; i++) {
        if (strcmp(items[i].key, key) == 0) {
            return items[i].value;
        }
    }
    return NULL;
}

void form_free(FormItem *items, int count) {
    for (int i = 0; i < count; i++) {
        free(items[i].key);
        free(items[i].value);
        items[i].key = NULL;
        items[i].value = NULL;
    }
}
