#include "Player.h"
#include "Utils/FileUtils.h"

auto Player::getGameMode() -> GameMode* {
	if (Utils::File::getVersion() == _("1.21.80"))
		return *reinterpret_cast<GameMode**>((uintptr_t)this + 0xA88);
	else if (Utils::File::getVersion() == _("1.21.73"))
		return *reinterpret_cast<GameMode**>((uintptr_t)this + 0xAD0);
	else if (Utils::File::getVersion() == _("1.21.72"))
		return *reinterpret_cast<GameMode**>((uintptr_t)this + 0xAD0);
	else if (Utils::File::getVersion() == _("1.21.71"))
		return *reinterpret_cast<GameMode**>((uintptr_t)this + 0xAD0);
	else if (Utils::File::getVersion() == _("1.21.70"))
		return *reinterpret_cast<GameMode**>((uintptr_t)this + 0xAD0);
	else
		return *reinterpret_cast<GameMode**>((uintptr_t)this + 0xAD8);
}

auto Player::getDeviceId() -> std::string {
	if (Utils::File::getVersion() == _("1.21.80"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC58)->c_str();
	else if (Utils::File::getVersion() == _("1.21.73"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xCA0)->c_str();
	else if (Utils::File::getVersion() == _("1.21.72"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xCA0)->c_str();
	else if (Utils::File::getVersion() == _("1.21.71"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xCA0)->c_str();
	else if (Utils::File::getVersion() == _("1.21.70"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xCA0)->c_str();
	else
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xCA0)->c_str();
}

auto Player::setDeviceId(std::string id) -> void {
	if (Utils::File::getVersion() == _("1.21.80"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC58)->set(id);
	else if (Utils::File::getVersion() == _("1.21.73"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xCA0)->set(id);
	else if (Utils::File::getVersion() == _("1.21.72"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xCA0)->set(id);
	else if (Utils::File::getVersion() == _("1.21.71"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xCA0)->set(id);
	else if (Utils::File::getVersion() == _("1.21.70"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xCA0)->set(id);
	else
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xCA0)->set(id);
}

auto Player::getPlayerInventory() -> PlayerInventory* {
	if (Utils::File::getVersion() == _("1.21.73"))
		return *reinterpret_cast<PlayerInventory**>((uintptr_t)this + 0x5C0);
	else if (Utils::File::getVersion() == _("1.21.72"))
		return *reinterpret_cast<PlayerInventory**>((uintptr_t)this + 0x5C0);
	else if (Utils::File::getVersion() == _("1.21.71"))
		return *reinterpret_cast<PlayerInventory**>((uintptr_t)this + 0x5C0);
	else if (Utils::File::getVersion() == _("1.21.70"))
		return *reinterpret_cast<PlayerInventory**>((uintptr_t)this + 0x5C0);
	else
		return *reinterpret_cast<PlayerInventory**>((uintptr_t)this + 0x5C8);
}

auto Player::getLevel() -> Level* {
	return *reinterpret_cast<Level**>((uintptr_t)this + 0x1D8);
}

auto Player::getContainerManagerModel() -> ContainerManagerModel* {
	if (Utils::File::getVersion() == _("1.21.73"))
		return *reinterpret_cast<ContainerManagerModel**>((uintptr_t)this + 0x5A8);
	else if (Utils::File::getVersion() == _("1.21.72"))
		return *reinterpret_cast<ContainerManagerModel**>((uintptr_t)this + 0x5A8);
	else if (Utils::File::getVersion() == _("1.21.71"))
		return *reinterpret_cast<ContainerManagerModel**>((uintptr_t)this + 0x5A8);
	else if (Utils::File::getVersion() == _("1.21.71"))
		return *reinterpret_cast<ContainerManagerModel**>((uintptr_t)this + 0x5A8);
	else
		return *reinterpret_cast<ContainerManagerModel**>((uintptr_t)this + 0x5B0);
}

auto Player::getLoopbackPacketSender() -> LoopbackPacketSender* {
	return *reinterpret_cast<LoopbackPacketSender**>((uintptr_t)this + 0x7D8);
}

auto Player::teleportTo(glm::vec3 pos) -> void {
	return reinterpret_cast<void(__thiscall*)(void*, glm::vec3)>((*reinterpret_cast<void***>(this))[21])(this, pos);
}

auto Player::swing() -> void {
	return reinterpret_cast<void(__thiscall*)(void*)>((*reinterpret_cast<void***>(this))[111])(this);
}

auto Player::setSprinting(bool state) -> void {
	return reinterpret_cast<void(__thiscall*)(void*, bool)>((*reinterpret_cast<void***>(this))[140])(this, state);
}

auto Player::displayClientMessage(std::string message) -> void {
	return reinterpret_cast<void(__thiscall*)(void*, std::string32, std::optional<std::string32>)>((*reinterpret_cast<void***>(this))[200])(this, std::string32(message), std::optional<std::string32>());
}
