#define KINO_USE_SHORT_NAMES

#include "KinoSearch/Util/Debug.h"

#if KINO_DEBUG_ENABLED

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

static char    env_cache_buf[256];
static char   *env_cache            = NULL;
static char   *env_cache_limit      = NULL;
static int     env_cache_is_current = 0;

/* Cache the system call to getenv. 
 */
static void
cache_debug_env_var(char *override)
{
    const char *debug_env = override ? override : getenv("KINO_DEBUG");
    if (debug_env != NULL) {
        size_t len = strlen(debug_env);
        if (len > sizeof(env_cache_buf) - 1) 
            len = sizeof(env_cache_buf) - 1;
        strncpy(env_cache_buf, debug_env, len);
        env_cache       = env_cache_buf;
        env_cache_limit = env_cache + len;
    }
    env_cache_is_current = 1;
}

void
kino_Debug_print_mess(const char *file, int line, const char *func, 
                      const char *pat, ...)
{
    va_list args;
    fprintf(stderr, "%s:%d %s(): ", file, line, func);
    va_start(args, pat);
    vfprintf(stderr, pat, args);
    va_end(args);
    fprintf(stderr, "\n");
}

int 
kino_Debug_debug_should_print(const char *path, const char *func) 
{
    if (!env_cache_is_current) 
        cache_debug_env_var(NULL);

    if (!env_cache) {
        /* Do not print if DEBUG environment var is not set. */
        return 0;
    }
    else {
        const char *test, *next;
        const char *file = strrchr(path, '/');
        const int filename_len = strlen(file);
        const int funcname_len = strlen(func);

        /* Use just file name if given path. */
        if (file) file++;
        else file = path;
   
        /* Split criteria on commas. Bail when we run out of critieria. */
        for (test = env_cache; test != NULL; test = next) {
            const char *last_char;

            /* Skip whitespace. */
            while (isspace(*test)) test++;
            if (test == env_cache_limit) return 0;

            /* Find end of criteria or end of string. */
            next = strchr(test, ',');
            last_char = next ? next - 1 : env_cache_limit - 1; 
            while (last_char > test && isspace(*last_char)) last_char--;

            if (*last_char == '*') {
                const int len = last_char - test;
                if (! strncmp(test, file, len)) return 1;
                if (! strncmp(test, func, len)) return 1;
            }
            else {
                if (! strncmp(test, file, filename_len)) return 1;
                if (! strncmp(test, func, funcname_len)) return 1;
            }
        }

        /* No matches against the DEBUG environment var, so don't print. */
        return 0;
    }
}

void
kino_Debug_set_env_cache(char *override)
{
    cache_debug_env_var(override);
}

#endif /* KINO_DEBUG */