#include <Windows.h>
#include <stdio.h>
#include "debug.h"

#include "..\Runtime\Runtime.h"

#ifdef _DEBUG
VOID OutputDebugRuntime(PRUNTIME pRuntime, LPSTR strFormat, ...)
{
	va_list vArgs;

	va_start(vArgs, strFormat);
	LPSTR strDebug = (LPSTR)API_ALLOC(pRuntime, (MAX_DEBUG_STRING + 2) * sizeof(CHAR)); // do not use zalloc here
	SecureZeroMemory(strDebug, (MAX_DEBUG_STRING + 2) * sizeof(CHAR));
	API_VSNPRINTF(strDebug, MAX_DEBUG_STRING, strFormat, vArgs);
	API_OUTPUTDEBUGSTRINGA(strDebug);

	API_FREE(pRuntime, strDebug);
}

VOID OutputDebug(LPSTR strFormat, ...)
{
	va_list vArgs;

	va_start(vArgs, strFormat);
	LPSTR strDebug = (LPSTR)malloc((MAX_DEBUG_STRING + 2) * sizeof(CHAR)); // do not use zalloc here
	SecureZeroMemory(strDebug, (MAX_DEBUG_STRING + 2) * sizeof(CHAR));
	_vsnprintf_s(strDebug, MAX_DEBUG_STRING, _TRUNCATE, strFormat, vArgs);
	OutputDebugString(strDebug);

	free(strDebug);
}

/* simple hexdump, taken from stackoverflow :) */
VOID HexDump(CHAR *desc, VOID *addr, UINT len) {
	unsigned int i;
	unsigned char buff[17];
	unsigned char *pc = (unsigned char*)addr;

	// Output description if given.
	if (desc != NULL)
		OutputDebug("%s:\n", desc);

	// Process every byte in the data.
	for (i = 0; i < len; i++) {
		// Multiple of 16 means new line (with line offset).

		if ((i % 16) == 0) {
			// Just don't print ASCII for the zeroth line.
			if (i != 0)
				OutputDebug("  %S\n", buff);

			// Output the offset.
			OutputDebug("  %04x ", i);
		}

		// Now the hex code for the specific character.
		OutputDebug(" %02x", pc[i]);

		// And store a printable ASCII character for later.
		if ((pc[i] < 0x20) || (pc[i] > 0x7e))
			buff[i % 16] = '.';
		else
			buff[i % 16] = pc[i];
		buff[(i % 16) + 1] = '\0';
	}

	// Pad out last line if not exactly 16 characters.
	while ((i % 16) != 0) {
		OutputDebug("   ");
		i++;
	}

	// And print the final ASCII bit.
	OutputDebug("  %S\n", buff);
}

VOID handleLastError(LPSTR szMessage)
{
	DWORD errCode = GetLastError();
	char *err;
	if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		NULL,
		errCode,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
		(LPTSTR)&err,
		0,
		NULL))
		return;

	char buffer[2048];
	_snprintf_s(buffer, sizeof(buffer), _TRUNCATE, "[E] GetLastError: %s: %s\n", szMessage, err);
	OutputDebugString(buffer);
	LocalFree(err);
}

VOID OutputDebugLastError(VOID)
{
	unsigned char buf[1024];
	FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 1024, NULL);
	OutputDebug(buf);
}

#endif