#define _GNU_SOURCE
#include <nss.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

#define JSON_FILE "/etc/wikidns.json"
#define MAX_LINE 256

static int lookup_ip(const char *hostname, char *ipbuf) {
    FILE *f = fopen(JSON_FILE, "r");
    if (!f)
        return 0;

    char line[256];
    char domain[128] = {0};
    char ip[64] = {0};

    while (fgets(line, sizeof(line), f)) {

        /* Parse domain_name */
        if (strstr(line, "\"domain_name\"")) {
            sscanf(line, " \"%*[^\"]\" : \"%127[^\"]\"", domain);
        }

        /* Parse first A record */
        if (strstr(line, "\"A\"")) {
            sscanf(line, " %*[^[][%63[^\"]", ip);
        }
    }

    fclose(f);

    if (strcmp(hostname, domain) == 0 && strlen(ip) > 0) {
        strcpy(ipbuf, ip);
        return 1;
    }

    return 0;
}

enum nss_status _nss_wikidns_gethostbyname2_r(
    const char *name,
    int af,
    struct hostent *result,
    char *buffer,
    size_t buflen,
    int *errnop,
    int *h_errnop)
{
    if (af != AF_INET)
        return NSS_STATUS_NOTFOUND;

    char ip[64];
    if (!lookup_ip(name, ip))
        return NSS_STATUS_NOTFOUND;

    if (buflen < 256) {
        *errnop = ERANGE;
        return NSS_STATUS_TRYAGAIN;
    }

    char *ptr = buffer;

    result->h_name = ptr;
    strcpy(ptr, name);
    ptr += strlen(name) + 1;

    result->h_aliases = (char **)ptr;
    ((char **)ptr)[0] = NULL;
    ptr += sizeof(char *);

    result->h_addrtype = AF_INET;
    result->h_length = 4;

    result->h_addr_list = (char **)ptr;
    ptr += 2 * sizeof(char *);

    result->h_addr_list[1] = NULL;
    result->h_addr_list[0] = ptr;

    inet_pton(AF_INET, ip, ptr);

    return NSS_STATUS_SUCCESS;
}
