#pragma once
#include "Utils/MemoryUtils.h"
#include "Client.h"

#include "SDK/ConnectionRequest.h"
#include "SDK/PrivateKeyManager.h"
#include "SDK/Certificate.h"
#include "SDK/SerializedSkin.h"

namespace Hooks {
	class ConnectionRequests {
	private:
		typedef auto(__thiscall* ConnectionRequest_create_217x_)(ConnectionRequest* _this, PrivateKeyManager* a2, Certificate* a3, __int64 a4, __int64 a5, __int64 a6, __int64 a7, __int64 a8, __int64 a9, SerializedSkin* a10, std::string32 a11, int a12, int a13, __int64 a14, char a15, char a16, void* a17, int a18, __int64 a19, __int64 a20, char a21, __int64 a22, __int64 a23, __int64 a24, char a25, __int64 a26) -> void*;
		typedef auto(__thiscall* ConnectionRequest_create_216x_)(ConnectionRequest* a1, PrivateKeyManager* a2, Certificate* a3, __int64 a4, __int64 a5, __int64 a6, __int64 a7, __int64 a8, __int64 a9, SerializedSkin* a10, std::string32 a11, int a12, int a13, int a14, void* a15, char a16, char a17, void* a18, int a19, __int64 a20, void* a21, char a22, void* a23, void* a24, void* a25, char a26, int a27, int a28) -> void*;
		inline static ConnectionRequest_create_217x_ connectionRequest_create_217x;
		inline static ConnectionRequest_create_216x_ connectionRequest_create_216x;

		static auto callback_create_217x(ConnectionRequest* _this, PrivateKeyManager* a2, Certificate* a3, __int64 a4, __int64 a5, __int64 a6, __int64 a7, __int64 a8, __int64 a9, SerializedSkin* a10, std::string32 a11, int a12, int a13, __int64 a14, char a15, char a16, void* a17, int a18, __int64 a19, __int64 a20, char a21, __int64 a22, __int64 a23, __int64 a24, char a25, __int64 a26) -> void*;
		static auto callback_create_216x(ConnectionRequest* _this, PrivateKeyManager* a2, Certificate* a3, __int64 a4, __int64 a5, __int64 a6, __int64 a7, __int64 a8, __int64 a9, SerializedSkin* a10, std::string32 a11, int a12, int a13, int a14, void* a15, char a16, char a17, void* a18, int a19, __int64 a20, void* a21, char a22, void* a23, void* a24, void* a25, char a26, int a27, int a28) -> void*;
	public:
		inline static int state = -1;
		static void Init() {
			std::thread([&] {
				void* pattern_create;
				if (Utils::File::getVersion() == _("1.21.73")) {
					pattern_create = Utils::Memory::FindPattern(_("40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 58 FF FF FF 48 81 EC A8 01 00 00 48 8B 05 3D 44"));

					state = Utils::Memory::CreateHook(pattern_create, (void*)&callback_create_217x, &connectionRequest_create_217x);
				}
				else if (Utils::File::getVersion() == _("1.21.72")) {
					pattern_create = Utils::Memory::FindPattern(_("40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 58 FF FF FF 48 81 EC A8 01 00 00 48 8B 05 2D 42"));

					state = Utils::Memory::CreateHook(pattern_create, (void*)&callback_create_217x, &connectionRequest_create_217x);
				}
				else if (Utils::File::getVersion() == _("1.21.71")) {
					pattern_create = Utils::Memory::FindPattern(_("40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 58 FF FF FF 48 81 EC A8 01 00 00 48 8B 05 8D"));

					state = Utils::Memory::CreateHook(pattern_create, (void*)&callback_create_217x, &connectionRequest_create_217x);
				}
				else if (Utils::File::getVersion() == _("1.21.70")) {
					pattern_create = Utils::Memory::FindPattern(_("40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 58 FF FF FF 48 81 EC A8 01 00 00 48 8B 05 8D"));

					state = Utils::Memory::CreateHook(pattern_create, (void*)&callback_create_217x, &connectionRequest_create_217x);
				}
				else {
					pattern_create = Utils::Memory::FindPattern(_("40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 18 F4"));

					state = Utils::Memory::CreateHook(pattern_create, (void*)&callback_create_216x, &connectionRequest_create_216x);
				}

				if (state == 0)
					MessageBoxA(0, _("The program was terminated due to an error.\nError code: 1-20"), _("Valkyrie"), MB_ICONERROR);
				else
					std::cout << _("Test 1-20... OK\n");
				}).detach();
		}
	};
}
