/*
	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License version 2 
	as published by the Free Software Foundation.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


	Copyright (C) 2006  Thierry Berger-Perrin <tbptbp@gmail.com>
*/
/*
	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License version 2
	as published by the Free Software Foundation.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


	Copyright (C) 2006  Thierry Berger-Perrin <tbptbp@gmail.com>
*/
#include "specifics.h"
#include <cstdio>
#include <cstdarg>
#include <cstring>

#include "sys_log.h"

extern void hud_log(const char * __restrict const s, const int len); // ugly

namespace sys {
	#if defined WINDOWS
		static inline int sprintf(char *buf, const char *fmt, va_list vl) { return vsprintf(buf, fmt, vl); }
	#elif defined LINUX
		static inline int sprintf(char *buf, const char *fmt, va_list vl) { return vsprintf(buf, fmt, vl); }
	#else
		#error not implemented.
	#endif



	static void console_log(const char * __restrict const s, const int len) {
		#ifdef WINDOWS
			// cygwin's printf ins't thread safe (re-entrancy issue i guess)
			//static bool_t debugzor = IsDebuggerPresent();
			static HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);

			//if (debugzor)
			//	OutputDebugStringA(s);

			// ahahahahahahah
			// if we're redirected and don't care about written chars (stuffing 0 instead of the dummy)
			// an exception gets thrown. hahahah. geez.
			DWORD dummy;
			WriteFile(out, s, len, &dummy, 0);
		#else
			std::printf(s);
		#endif
	}

	static void do_log(const char * __restrict const s, const int len) {
		console_log(s, len);
		hud_log(s, len);
	}


	void log(const char * __restrict const fmt, ...) {
		enum { buf_len = 512 };
		char buf[buf_len];

		int len;
		va_list vl; va_start(vl, fmt);
		{
			len = sys::sprintf(buf, fmt, vl);	// user32. simpler than ntdll!_vsnwprintf
		}
		va_end(vl);
		do_log(buf, len);
	}

	format_t::format_t(const char * __restrict const fmt, ...) {
		va_list vl; va_start(vl, fmt);
		{
			len = vsnprintf(buf, buf_size, fmt, vl);
			buf[buf_size-1] = 0;
		}
		va_end(vl);
	}

	void format_t::log() const {
		do_log(buf, len);
	}
}
