#include "extension.h"
#include "network.h"
#include "util.h"
#include <ctime>
#include <QStringList>

extern const wchar_t* TRANSLATION_ERROR;

const char* TRANSLATION_PROVIDER = "Google";
QStringList languages
{
	"English: en",
	"Afrikaans: af",
	"Arabic: ar",
	"Albanian: sq",
	"Belarusian: be",
	"Bengali: bn",
	"Bosnian: bs",
	"Bulgarian: bg",
	"Catalan: ca",
	"Chinese(Simplified): zh-CH",
	"Chinese(Traditional): zh-TW",
	"Croatian: hr",
	"Czech: cs",
	"Danish: da",
	"Dutch: nl",
	"Esperanto: eo",
	"Estonian: et",
	"Filipino: tl",
	"Finnish: fi",
	"French: fr",
	"Galician: gl",
	"German: de",
	"Greek: el",
	"Hebrew: iw",
	"Hindi: hi",
	"Hungarian: hu",
	"Icelandic: is",
	"Indonesian: id",
	"Irish: ga",
	"Italian: it",
	"Japanese: ja",
	"Klingon: tlh",
	"Korean: ko",
	"Latin: la",
	"Latvian: lv",
	"Lithuanian: lt",
	"Macedonian: mk",
	"Malay: ms",
	"Maltese: mt",
	"Norwegian: no",
	"Persian: fa",
	"Polish: pl",
	"Portuguese: pt",
	"Romanian: ro",
	"Russian: ru",
	"Serbian: sr",
	"Slovak: sk",
	"Slovenian: sl",
	"Somali: so",
	"Spanish: es",
	"Swahili: sw",
	"Swedish: sv",
	"Thai: th",
	"Turkish: tr",
	"Ukranian: uk",
	"Urdu: ur",
	"Vietnamese: vi",
	"Welsh: cy",
	"Yiddish: yi",
	"Zulu: zu"
};
Synchronized<std::wstring> translateTo = L"en";

std::wstring GetTranslationUri(const std::wstring& text, unsigned TKK)
{
	// If no TKK available, use this uri. Can't use too much or google will detect unauthorized access
	if (!TKK) return FormatString(L"/translate_a/single?client=gtx&dt=ld&dt=rm&dt=t&tl=%s&q=%s", translateTo->c_str(), text);

	// Artikash 8/19/2018: reverse engineered from translate.google.com
	std::wstring escapedText;
	unsigned a = _time64(NULL) / 3600, b = a; // <- the first part of TKK
	for (unsigned char ch : WideStringToString(text))
	{
		escapedText += FormatString(L"%%%02X", (int)ch);
		a += ch;
		a += a << 10;
		a ^= a >> 6;
	}
	a += a << 3;
	a ^= a >> 11;
	a += a << 15;
	a ^= TKK;
	a %= 1000000;
	b ^= a;

	return FormatString(L"/translate_a/single?client=t&dt=ld&dt=rm&dt=t&tl=%s&tk=%u.%u&q=%s", translateTo->c_str(), a, b, escapedText);
}

std::pair<bool, std::wstring> Translate(const std::wstring& text)
{
	static unsigned TKK = 0;
	if (!TKK)
		if (HttpRequest httpRequest{ L"Mozilla/5.0 Textractor", L"translate.google.com", L"GET", L"/" })
			if (std::wsmatch results; std::regex_search(httpRequest.response, results, std::wregex(L"(\\d{7,})'")))
				_InterlockedCompareExchange(&TKK, stoll(results[1]), 0);

	if (HttpRequest httpRequest{ L"Mozilla/5.0 Textractor", L"translate.google.com", L"GET", GetTranslationUri(text, TKK).c_str() })
	{
		// Response formatted as JSON: starts with "[[[" and translation is enclosed in quotes followed by a comma
		if (httpRequest.response[0] == L'[')
		{
			std::wstring translation;
			for (std::wsmatch results; std::regex_search(httpRequest.response, results, std::wregex(L"\\[\"(.*?)\",[n\"]")); httpRequest.response = results.suffix())
				translation += std::wstring(results[1]) + L" ";
			if (!translation.empty()) return { true, translation };
		}
		return { false, FormatString(L"%s (TKK=%u)", TRANSLATION_ERROR, _InterlockedExchange(&TKK, 0)) };
	}
	else return { false, FormatString(L"%s (code=%u)", TRANSLATION_ERROR, httpRequest.errorCode) };
}