/*
 * Debugging library routines
 */
#if defined(ENABLE_LIBYAHOO_DEBUG)

#include "config.h"
#include "libyahoo-debug.h"

#include <stdlib.h>
#include <stdio.h>
#if defined(HAVE_STDARG_H)
#include <stdarg.h>
#endif
#include <ctype.h>

#if defined(HAVE_STRING_H)
#include <string.h>
#elif defined(HAVE_STRINGS_H)
#include <strings.h>
#endif

static FILE *debugfile = NULL;
static char *yahoo_dbg_EnabledKeys[128] = { NULL };	/* should be more than enough */
static int yahoo_dbg_MaxEnabledKey = -1;

char *yahoo_unraw_buffer(char *buffer, unsigned int len)
{
	char *un_raw = NULL, *q = un_raw, *p = buffer;
	unsigned int i = 0, n = 1;

	if (!(q = un_raw = malloc(4 * len)))
	  return NULL;

	for (i = 0; i < len; ++i)
	{
		if (isprint((int) *p))
		{
			if ('\\' == *p)
			{
				*q++ = *p++;
				*q++ = *p;
				n += 2;
			}
			else
			{
				*q++ = *p++;
				++n;
			}
		}
		else
		{
			unsigned char c = *p;

			snprintf(q, 5, "\\%03o", c);
			++p;
			q += 4;
			n += 4;
		}
	}

	*q = '\0';

	un_raw = realloc (un_raw, n + 1);

	return un_raw;
}

/* these routines currently do a really inneficient linear search, 
   but it's not like they need to be really fast - they are just for
   debugging purposes */

int yahoo_dbg_Open(const char *file)
{
	if (debugfile && debugfile != stdout)
	{
		fclose(debugfile);
		debugfile = NULL;
	}

	if (!file)
	{
		fprintf(stderr,
			"yahoo_dbg_Open Error: File is null, using stdout.\n");
		debugfile = stdout;
		return 1;
	}

	if ((debugfile = fopen(file, "a")) == NULL)
	{
		fprintf(stderr, "yahoo_dbg_Open Error: Couldn't open output file.\n");
		fprintf(stderr, "                Falling back to stdout.\n");
		debugfile = stdout;
		return 1;
	}

	return 0;
}

int yahoo_dbg_Disable(const char *key)
{
	int i;

	if (!key)
	{
		fprintf(stderr, "yahoo_dbg_Disable Error: key is null.\n");
		return 1;
	}
	for (i = 0; i <= yahoo_dbg_MaxEnabledKey; i++)
	{
		if (yahoo_dbg_EnabledKeys[i]
			&& !strcmp(yahoo_dbg_EnabledKeys[i], key))
		{
			free(yahoo_dbg_EnabledKeys[i]);
			yahoo_dbg_EnabledKeys[i] = NULL;
			return 0;
		}
	}
	return 1;
}

int yahoo_dbg_Enable(const char *key)
{
	int i;

	if (!key)
	{
		fprintf(stderr, "yahoo_dbg_Enable Error: key is null.\n");
		return 1;
	}
	for (i = 0; i <= yahoo_dbg_MaxEnabledKey; i++)
	{
		if (yahoo_dbg_EnabledKeys[i]
			&& !strcmp(yahoo_dbg_EnabledKeys[i], key))
		{
			return 0;			/* already enabled */
		}
	}
	yahoo_dbg_EnabledKeys[yahoo_dbg_MaxEnabledKey + 1] = NULL;
	for (i = 0; i <= yahoo_dbg_MaxEnabledKey + 1; i++)
	{
		if (!yahoo_dbg_EnabledKeys[i])
		{
			yahoo_dbg_EnabledKeys[i] = strdup(key);
			if (i > yahoo_dbg_MaxEnabledKey)
			{
				yahoo_dbg_MaxEnabledKey = i;
			}
			return 0;			/* already enabled */
		}
	}
	return 0;
}

int yahoo_dbg_Print(const char *key, char *format, ...)
{
	va_list args;

	if (!key)
	{
		fprintf(stderr, "yahoo_dbg_Print Error: key is null.\n");
		return 1;
	}
	if (!format)
	{
		fprintf(stderr, "yahoo_dbg_Print Error: format is null.\n");
		return 1;
	}

	if (!debugfile)
	{
		debugfile = stdout;
	}

	if (yahoo_dbg_IsEnabled(key) || yahoo_dbg_IsEnabled("all"))
	{
		va_start(args, format);
		vfprintf(debugfile, format, args);
		va_end(args);

		fflush(debugfile);
	}
	return 0;
}

int yahoo_dbg_Close(void)
{
	if (debugfile && debugfile != stdout)
	{
		fclose(debugfile);
		debugfile = NULL;
	}
	return 0;
}

int yahoo_dbg_IsEnabled(const char *key)
{
	int i;

	for (i = 0; i <= yahoo_dbg_MaxEnabledKey; i++)
	{
		if (!strcmp(yahoo_dbg_EnabledKeys[i], key))
		{
			return 1;			/* is enabled */
		}
	}
	return 0;
}

#else

/* Debugging is not enabled, so do an inline routines that do nothing */
/* Hopefully the compiler will completely optimize these routines away */

inline char *yahoo_unraw_buffer(const char *buffer, unsigned int len)
{
	return (char *) 0;
}

inline int yahoo_dbg_Open(char *file)
{
	return 0;
}

inline int yahoo_dbg_Disable(char *key)
{
	return 0;
}

inline int yahoo_dbg_Enable(char *key)
{
	return 0;
}

inline int yahoo_dbg_Print(char *key, char *format, ...)
{
	return 0;
}

inline int yahoo_dbg_Close(void)
{
	return 0;
}

inline int yahoo_dbg_IsEnabled(char *key)
{
	return 0;
}

#endif
