/*
Minetest
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

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 Lesser General Public License for more details.

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

#include <string>
#include <string.h>
#include <iostream>
#include <stdlib.h>
#include "gettext.h"
#include "util/string.h"
#include "log.h"

#if USE_GETTEXT && defined(_MSC_VER)
#include <windows.h>
#include <map>
#include <direct.h>
#include "filesys.h"

#define setlocale(category, localename) \
	setlocale(category, MSVC_LocaleLookup(localename))

static std::map<std::wstring, std::wstring> glb_supported_locales;

/******************************************************************************/
BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr)
{
	char* endptr = 0;
	int LOCALEID = strtol(pStr, &endptr,16);

	wchar_t buffer[LOCALE_NAME_MAX_LENGTH];
	memset(buffer, 0, sizeof(buffer));
	if (GetLocaleInfoW(
		LOCALEID,
		LOCALE_SISO639LANGNAME,
		buffer,
		LOCALE_NAME_MAX_LENGTH)) {

		std::wstring name = buffer;

		memset(buffer, 0, sizeof(buffer));
		GetLocaleInfoW(
		LOCALEID,
		LOCALE_SISO3166CTRYNAME,
		buffer,
		LOCALE_NAME_MAX_LENGTH);

		std::wstring country = buffer;

		memset(buffer, 0, sizeof(buffer));
		GetLocaleInfoW(
		LOCALEID,
		LOCALE_SENGLISHLANGUAGENAME,
		buffer,
		LOCALE_NAME_MAX_LENGTH);

		std::wstring languagename = buffer;

		/* set both short and long variant */
		glb_supported_locales[name] = languagename;
		glb_supported_locales[name + L"_" + country] = languagename;
	}
	return true;
}

/******************************************************************************/
const char* MSVC_LocaleLookup(const char* raw_shortname) {

	/* NULL is used to read locale only so we need to return it too */
	if (raw_shortname == NULL) return NULL;

	std::string shortname(raw_shortname);
	if (shortname == "C") return "C";
	if (shortname == "") return "";

	static std::string last_raw_value = "";
	static std::string last_full_name = "";
	static bool first_use = true;

	if (last_raw_value == shortname) {
		return last_full_name.c_str();
	}

	if (first_use) {
		EnumSystemLocalesA(UpdateLocaleCallback, LCID_SUPPORTED | LCID_ALTERNATE_SORTS);
		first_use = false;
	}

	last_raw_value = shortname;

	if (glb_supported_locales.find(utf8_to_wide(shortname)) != glb_supported_locales.end()) {
		last_full_name = wide_to_utf8(
			glb_supported_locales[utf8_to_wide(shortname)]);
		return last_full_name.c_str();
	}

	/* empty string is system default */
	errorstream << "MSVC_LocaleLookup: unsupported locale: \"" << shortname
				<< "\" switching to system default!" << std::endl;
	return "";
}

#endif

/******************************************************************************/
void init_gettext(const char *path, const std::string &configured_language,
	int argc, char *argv[])
{
#if USE_GETTEXT
	// First, try to set user override environment
	if (!configured_language.empty()) {
#ifndef _WIN32
		// Add user specified locale to environment
		setenv("LANGUAGE", configured_language.c_str(), 1);

		// Reload locale with changed environment
		setlocale(LC_ALL, "");
#elif defined(_MSC_VER)
		std::string current_language;
		const char *env_lang = getenv("LANGUAGE");
		if (env_lang)
			current_language = env_lang;

		_putenv(("LANGUAGE=" + configured_language).c_str());
		SetEnvironmentVariableA("LANGUAGE", configured_language.c_str());

#ifndef SERVER
		// Hack to force gettext to see the right environment
		if (current_language != configured_language) {
			errorstream << "MSVC localization workaround active.  "
				"Restarting " PROJECT_NAME_C " in a new environment!" << std::endl;

			std::string parameters;

			for (unsigned int i = 1; i < argc; i++) {
				if (!parameters.empty())
					parameters += ' ';

				parameters += argv[i];
			}

			const char *ptr_parameters = NULL;

			if (!parameters.empty())
				ptr_parameters = parameters.c_str();

			// Allow calling without an extension
			std::string app_name = argv[0];
			if (app_name.compare(app_name.size() - 4, 4, ".exe") != 0)
				app_name += ".exe";

			STARTUPINFO startup_info = {0};
			PROCESS_INFORMATION process_info = {0};

			bool success = CreateProcess(app_name.c_str(), (char *)ptr_parameters,
				NULL, NULL, false, DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT,
				NULL, NULL, &startup_info, &process_info);

			if (success) {
				exit(0);
				// NOTREACHED
			} else {
				char buffer[1024];

				FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
					MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), buffer,
					sizeof(buffer) - 1, NULL);

				errorstream << "*******************************************************" << std::endl;
				errorstream << "CMD: " << app_name << std::end<span class="hl com">/*</span>
<span class="hl com">Minetest</span>
<span class="hl com">Copyright (C) 2010-2013 celeron55, Perttu Ahola &lt;celeron55&#64;gmail.com&gt;</span>
<span class="hl com"></span>
<span class="hl com">This program is free software; you can redistribute it and/or modify</span>
<span class="hl com">it under the terms of the GNU Lesser General Public License as published by</span>
<span class="hl com">the Free Software Foundation; either version 2.1 of the License, or</span>
<span class="hl com">(at your option) any later version.</span>
<span class="hl com"></span>
<span class="hl com">This program is distributed in the hope that it will be useful,</span>
<span class="hl com">but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span class="hl com">MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<span class="hl com">GNU Lesser General Public License for more details.</span>
<span class="hl com"></span>
<span class="hl com">You should have received a copy of the GNU Lesser General Public License along</span>
<span class="hl com">with this program; if not, write to the Free Software Foundation, Inc.,</span>
<span class="hl com">51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span>
<span class="hl com">*/</span>

<span class="hl ppc">#include</span> <span class="hl pps">&quot;staticobject.h&quot;</span><span class="hl ppc"></span>
<span class="hl ppc">#include</span> <span class="hl pps">&quot;util/serialize.h&quot;</span><span class="hl ppc"></span>

<span class="hl kwb">void</span> <span class="hl kwc">StaticObject</span><span class="hl opt">::</span><span class="hl kwd">serialize</span><span class="hl opt">(</span><span class="hl kwc">std</span><span class="hl opt">::</span>ostream <span class="hl opt">&amp;</span>os<span class="hl opt">)</span>
<span class="hl opt">{</span>
	<span class="hl slc">// type</span>
	<span class="hl kwd">writeU8</span><span class="hl opt">(</span>os<span class="hl opt">,<