 // Fill out your copyright notice in the Description page of Project Settings.


#include "LovenseWebThread.h"


static char* FStringToUTF8(const FString& fString)
{
	const TCHAR* tcharArray = *fString;

	int32 utf8Length = 0;
	for (const TCHAR* ptr = tcharArray; *ptr != 0; ++ptr)
	{
		if (*ptr < 0x80)
		{
			utf8Length++; 
		}
		else if (*ptr < 0x800)
		{
			utf8Length += 2; 
		}
		else
		{
			utf8Length += 3; 
		}
	}
	utf8Length++;

	char* utf8String = new char[utf8Length];
	if (!utf8String)
	{
		return nullptr; 
	}
	int32 written = 0;
	for (const TCHAR* ptr = tcharArray; *ptr != 0 && written < utf8Length - 1; ++ptr)
	{
		if (*ptr < 0x80)
		{
			utf8String[written++] = static_cast<char>(*ptr);
		}
		else if (*ptr < 0x800)
		{
			utf8String[written++] = 0xC0 | (*ptr >> 6);
			utf8String[written++] = 0x80 | (*ptr & 0x3F);
		}
		else
		{
			utf8String[written++] = 0xE0 | (*ptr >> 12);
			utf8String[written++] = 0x80 | ((*ptr >> 6) & 0x3F);
			utf8String[written++] = 0x80 | (*ptr & 0x3F);
		}
	}
	utf8String[written] = 0;

	return utf8String;
}

size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
	((FString*)userp)->Append((char*)contents, size * nmemb);
	return size * nmemb;
}

void LovenseWebThread::PauseThread() {

}
void LovenseWebThread::WakeUpThread() {

}
void LovenseWebThread::StopThread() {

}
void LovenseWebThread::Suspend(bool bSuspend) {

}

bool LovenseWebThread::Init() {
	return true;
};
uint32 LovenseWebThread::Run() {
	CURL* curl = curl_easy_init();
	const char* utf8Body = nullptr;
	if (curl)
	{
		curl_easy_setopt(curl, CURLOPT_URL, TCHAR_TO_UTF8(*url));
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

	}
	if (bIgnoreSSL)
	{
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
	}
	else {
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

	}
	if (method == "POST")
	{
		curl_easy_setopt(curl, CURLOPT_POST, 1L);
	}
	else if (method == "GET")
	{
	}
	if (!body.IsEmpty())
	{
		utf8Body = FStringToUTF8(body);
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, utf8Body);
	}
	else {

	}
	bool hasHeader = false;
	struct curl_slist* headerList = NULL;
	for (auto& header : headers)
	{
		FString headerString = header.Key + ": " + header.Value;
		headerList = curl_slist_append(headerList, TCHAR_TO_UTF8(*headerString));
		hasHeader = true;
	}
	if (hasHeader) 
	{
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerList);
	}

	FString responseStr;
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseStr);

	CURLcode res = curl_easy_perform(curl);
	if (res != CURLE_OK)
	{
//		std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
	}
	else
	{
		responseString = responseStr;
	}

	curl_easy_cleanup(curl);
	if (headerList)
	{
		curl_slist_free_all(headerList);
	}
	if (!body.IsEmpty())
	{
		delete utf8Body;
	}
	return 0;
};
void LovenseWebThread::Stop() {

};
void LovenseWebThread::Exit() {
	if (CallbackGetRemote != NULL) {
		AsyncTask(ENamedThreads::GameThread, [this] {
			CallbackGetRemote(responseString, getAdapter);
		});
	}
	else if (CallbackGetToys) {
		AsyncTask(ENamedThreads::GameThread, [this] {
			CallbackGetToys(responseString, getToys);
		});
	} else if (CallbackCmdResponse != NULL) {
		AsyncTask(ENamedThreads::GameThread, [this] {
			CallbackCmdResponse(responseString,cmdResponse);
		});
	}
	else if (Callback != NULL) {
		AsyncTask(ENamedThreads::GameThread, [this] {
			Callback(responseString);
			});
	}
};