/*
 * PtokaX - hub server for Direct Connect peer to peer network.

 * Copyright (C) 2004-2022  Petr Kozelka, PPK at PtokaX dot org

 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3
 * 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, see <http://www.gnu.org/licenses/>.
 */

//---------------------------------------------------------------------------
#include "stdinc.h"
//---------------------------------------------------------------------------
#include "LanguageXml.h"
#include "LanguageStrings.h"
#include "LanguageManager.h"
//---------------------------------------------------------------------------
#include "SettingManager.h"
#include "ServerManager.h"
#include "utility.h"
#include "tinyxml.h"
//---------------------------------------------------------------------------
#ifdef _WIN32
#pragma hdrstop
#endif
//---------------------------------------------------------------------------
LanguageManager * LanguageManager::m_Ptr = nullptr;
//---------------------------------------------------------------------------

LanguageManager::LanguageManager(void)
{
	for (size_t szi = 0; szi < LANG_IDS_END; szi++)
	{
		size_t szTextLen = strlen(LangStr[szi]);
		m_sTexts[szi] = (char *)malloc(szTextLen + 1);
		if (m_sTexts[szi] == NULL)
		{
			AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes in LanguageManager::LanguageManager\n", szTextLen+1);

			exit(EXIT_FAILURE);
		}
		memcpy(m_sTexts[szi], LangStr[szi], szTextLen);
		m_ui16TextsLens[szi] = (uint16_t)szTextLen;
		m_sTexts[szi][m_ui16TextsLens[szi]] = '\0';
	}
}
//---------------------------------------------------------------------------

LanguageManager::~LanguageManager(void)
{
	for (size_t szi = 0; szi < LANG_IDS_END; szi++)
	{
		free(m_sTexts[szi]);
	}
}
//---------------------------------------------------------------------------

void LanguageManager::Load()
{
	if (SettingManager::m_Ptr->m_sTexts[SETTXT_LANGUAGE] == NULL)
	{
		for (size_t szi = 0; szi < LANG_IDS_END; szi++)
		{
			char * sOldText = m_sTexts[szi];

			size_t szTextLen = strlen(LangStr[szi]);
			m_sTexts[szi] = (char *)realloc(sOldText, szTextLen + 1);
			if (m_sTexts[szi] == NULL)
			{
				m_sTexts[szi] = sOldText;

				AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in LanguageManager::Load\n", szTextLen+1);

				continue;
			}

			memcpy(m_sTexts[szi], LangStr[szi], szTextLen);
			m_ui16TextsLens[szi] = (uint16_t)szTextLen;
			m_sTexts[szi][m_ui16TextsLens[szi]] = '\0';
		}
	}
	else
	{
#ifdef _WIN32
		string sLanguageFile = ServerManager::m_sPath + "\\language\\" + string(SettingManager::m_Ptr->m_sTexts[SETTXT_LANGUAGE],
#else
		string sLanguageFile = ServerManager::m_sPath + "/language/" + string(SettingManager::m_Ptr->m_sTexts[SETTXT_LANGUAGE],
#endif
		                       (size_t)SettingManager::m_Ptr->m_ui16TextsLens[SETTXT_LANGUAGE]) + ".xml";

		TiXmlDocument doc(sLanguageFile.c_str());
		if (doc.LoadFile() == false)
		{
			if (doc.ErrorId() != TiXmlBase::TIXML_ERROR_OPENING_FILE && doc.ErrorId() != TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY)
			{
				int iMsgLen = snprintf(ServerManager::m_pGlobalBuffer, ServerManager::m_szGlobalBufferSize, "Error loading file %s.xml. %s (Col: %d, Row: %d)", SettingManager::m_Ptr->m_sTexts[SETTXT_LANGUAGE], doc.ErrorDesc(), doc.Column(), doc.Row());
				if (iMsgLen > 0)
				{
#ifdef _BUILD_GUI
					::MessageBox(NULL, ServerManager::m_pGlobalBuffer, g_sPtokaXTitle, MB_OK | MB_ICONERROR);
#else
					AppendLog(ServerManager::m_pGlobalBuffer);
#endif
				}
			}
		}
		else
		{
			TiXmlHandle cfg(&doc);
			TiXmlNode *language = cfg.FirstChild("Language").Node();
			if (language != NULL)
			{
				TiXmlNode *text = nullptr;
				while ((text = language->IterateChildren(text)) != NULL)
				{
					if (text->ToElement() == NULL)
					{
						continue;
					}

					const char * sName = text->ToElement()->Attribute("Name");
					const char * sText = text->ToElement()->GetText();
					size_t szLen = (sText != NULL ? strlen(sText) : 0);
					if (szLen != 0 && szLen < 129)
					{
						for (size_t szi = 0; szi < LANG_IDS_END; szi++)
						{
							if (strcmp(LangXmlStr[szi], sName) == 0)
							{
								char * sOldText = m_sTexts[szi];
								m_sTexts[szi] = (char *)realloc(sOldText, szLen + 1);
								if (m_sTexts[szi] == NULL)
								{
									m_sTexts[szi] = sOldText;

									AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in LanguageManager::Load1\n", szLen+1);

									break;
								}

								memcpy(m_sTexts[szi], sText, szLen);
								m_ui16TextsLens[szi] = (uint16_t)szLen;
								m_sTexts[szi][m_ui16TextsLens[szi]] = '\0';
								break;
							}
						}
					}
				}
			}
		}
	}
}
//---------------------------------------------------------------------------

void LanguageManager::GenerateXmlExample()
{
	TiXmlDocument xmldoc;
	xmldoc.InsertEndChild(TiXmlDeclaration("1.0", "windows-1252", "yes"));
	TiXmlElement xmllanguage("Language");
	xmllanguage.SetAttribute("Name", "Example English Language");
	xmllanguage.SetAttribute("Author", "PtokaX");
	xmllanguage.SetAttribute("Version", PtokaXVersionString " build " BUILD_NUMBER);

	for (int i = 0; i < LANG_IDS_END; i++)
	{
		TiXmlElement xmlstring("String");
		xmlstring.SetAttribute("Name", LangXmlStr[i]);
		xmlstring.InsertEndChild(TiXmlText(LangStr[i]));
		xmllanguage.InsertEndChild(xmlstring);
	}

	xmldoc.InsertEndChild(xmllanguage);
	xmldoc.SaveFile("English.xml.example");
}
//---------------------------------------------------------------------------

V1042 This file is marked with copyleft license, which requires you to open the derived source code.